В С++, какая разница в поведении между std::pair<const T, const U>
и const std::pair<T, U>
?
Разница между парой констант и пар const
Ответ 1
Основное отличие заключается в том, что они представляют собой разные несвязанные типы (с некоторыми неявными преобразованиями между ними).
void f(std::pair<std::string,std::string> const &);
std::string longstring();
int main() {
std::pair<const std::string,const std::string> pc
= std::make_pair(longstring(),longstring());
f(pc);
const std::pair<std::string,std::string> cp
= std::make_pair(longstring(),longstring());
f(cp);
}
Пока существуют неявные преобразования, которые позволяют f(pc)
компилировать, эта строка включает преобразование, а преобразование включает в себя создание копии longstring()
s. С другой стороны, вызов f(cp)
связывает постоянную ссылку на существующую пару по типу, не требуя каких-либо копий.
Тот факт, что компилятор позволяет вам писать аналогичный код, не означает, что код скомпилирован, чтобы сделать то же самое. Это особенно справедливо для типов с неявными преобразованиями, как в случае std::pair
Это обычная ошибка при написании функторов для работы с элементами, хранящимися на картах, где несоответствие аргумента функтора приведет к ненужному копированию данных объекта:
std::map<int,std::string> m = create_map();
std::for_each(m.begin(),m.end(),
[](std::pair<int,std::string> const &r) {
std::cout << r.second << " ";
});
В приведенной выше лямбда не указан правильный аргумент (std::pair<int,std::string
vs. std::pair<const int,std::string>
), что заставляет каждый вызов копировать как индекс, так и значение (т.е. все строки будут скопированы до std::pair<int,std::string>
а затем ссылка на аргумент для лямбда). Простой рекомендацией в этом случае было бы использование std::map<int,std::string>::value_type const &
для типа аргумента.
Ответ 2
Из тестов, которые я сделал, поведение одинаковое.
#include <utility>
int main() {
std::pair<const int, const int> p = std::make_pair(2,3);
p = std::make_pair(3, 4); // error
p.first = 5; // also error
const std::pair<int, int> p2 = std::make_pair(4,5);
p2 = std::make_pair(4, 5); // error
p2.first = 0; // error
return 0;
}