Подтвердить что ты не робот

Разница между парой констант и пар const

В С++, какая разница в поведении между std::pair<const T, const U> и const std::pair<T, U>?

4b9b3361

Ответ 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;
}