operator[]
в std::map
имеет разницу в том, что в стандарте он определяется как возвращающий (*((insert(make_pair(x, T()))).first)).second
, тогда как в STL m[k]
определяется как эквивалент (*((m.insert(value_type(k, data_type()))).first)).second
.
Разницаэто то, что соответствующие реализации C ++ вызывают make_pair
, тогда как STL создает пару напрямую.Я могу думать о двух различиях, которые это делает:
1) Стандарт разрешает дополнительную копию пары (и, следовательно, объектов ключа и данных), если RVO не удается включить вызов для make_pair
,Насколько я понимаю, STL не разрешает эту копию (хотя, конечно, есть дальнейшая копия в insert
).Это имеет значение, если ключ или тип значения имеют конструкторы копирования с наблюдаемыми побочными эффектами.
2) Пользователи могут специализироваться либо std::make_pair
, либо std::pair
.Если они специализируются make_pair
, то их код гарантированно вызывается в стандарте C ++ и гарантированно не вызывается в STL.
Такие специализации вызывают UB, если они не удовлетворяют требованиям шаблона,хотя и в случае make_pair
я думаю, что, если он имеет какие-либо наблюдаемые эффекты, кроме эффектов создания пары, то он не удовлетворяет требованиям.Так что в этом случае может быть трудно или невозможно написать специализацию, гарантированную , которая позволит вам определить, вызвана она или нет.На практике, если реализация сделала очевидную вещь и использовала код из стандарта, вы легко увидите разницу ...
Пользователи также могут ADL-перегрузить make_pair
, то же самое предостережение, с дополнительнымсложность в том, что я не совсем уверен, требуют ли упоминания в стандарте вызовов без оговорок, чтобы реализация выполняла тот же неквалифицированный вызов.Я уверен, что слышал, что некоторые реализации в таких случаях совершали полные вызовы std::whatever
, возможно, ошибочно.
Это то, что вам нужно?