Давайте рассмотрим ваши варианты по одному (плюс один или два, которые вы не упомянули).
Варианты 1 и 6 практически идентичны с точки зрения семантики. using
и pair
— это просто два разных способа написания value_type для map
. Если вы хотите, вы можете добавить третий способ, используя оператор typedef
вместо оператора using
:
typedef std::map<uint32_t, std::string>::value_type valType;
... и иметь эквивалент C++98/03 вашего #6. Все три в конечном итоге делают одно и то же: создают временный объект типа pair
и вставляют его в файл map
.
Версии 3 и 5 делают почти то же самое. Они используют emplace
, но то, что они передают, уже является объектом value_type map
. К моменту начала выполнения самого emplace
тип объекта, который будет храниться в карте, уже создан. Опять же, единственная разница между ними заключается в синтаксисе, используемом для указания типа pair
, и, опять же, с typedef
, как я показал выше, вы могли бы получить C++98/03, эквивалентный тому, который в настоящее время имеет оператор using
. Тот факт, что в версии 3 используется insert
, а в версии 5 — emplace
, практически не имеет значения — к моменту вызова любой из функций-членов мы уже создали и передали временный объект.
Варианты 2 и 4 на самом деле используют emplace
больше, чем это, вероятно, было задумано — передача отдельных компонентов, совершенная переадресация их в конструктор и создание объекта value_type
на месте, поэтому мы избегаем создания каких-либо временных объектов в любой момент. Основное (единственное?) различие между ними заключается в том, является ли вещь, которую мы передаем для компонента string
value_type, строковым литералом (из которого необходимо создать временный объект std::string
) или объектом std::string
, который был создан заранее. времени.
Выбор между ними может быть нетривиальным. Если (как указано выше) вы делаете это только один раз, на самом деле это не будет иметь никакого значения — независимо от того, когда вы его создаете, вы создаете строковый объект, а затем помещаете его в map
.
Таким образом, чтобы действительно изменить ситуацию, нам нужно предварительно создать строковый объект, а затем несколько раз вставить тот же самый строковый объект в файл map
. Это довольно необычно само по себе — в большинстве случаев вы будете делать что-то вроде считывания внешних данных в строку, а затем вставлять их в map
. Если вы действительно неоднократно вставляете (созданный из std::string
) один и тот же строковый литерал, велики шансы, что любой разумный компилятор сможет определить, что результирующая строка является инвариантной к циклу, и выведет конструкцию string
из цикла, дав, по сути, одно и то же эффект.
Итог: что касается использования самого map
, варианты 2 и 4 эквивалентны. Между этими двумя я бы не стал прилагать никаких реальных усилий, чтобы использовать вариант 2 вместо варианта 4 (т. е. предварительное создание строки), но это, вероятно, произойдет в большинстве случаев просто потому, что вставка одного строкового литерала в карту редко полезно. Строка, которую вы помещаете в карту, гораздо чаще будет поступать из какого-то внешнего источника данных, поэтому у вас будет string
, потому что это то, что (например) std::getline
дало вам, когда вы читаете данные из файла.
person
Jerry Coffin
schedule
21.01.2015