Как set::emplace обрабатывает объекты, которые уже находятся в наборе?

У меня есть набор объектов, и я хочу использовать emplace для добавления объектов в набор. Если эквивалентный объект еще не существует в наборе, set::emplace создает объект и помещает его в набор. Если в наборе уже есть эквивалентный объект, set::emplace не добавляет объект в список. В этом случае он создает объект и уничтожает его, создает и сливает или вообще не создает? Или сделает что-то еще?

С++ 11, gcc 4.7.0


person Qaz    schedule 27.03.2014    source источник
comment
Я очень уверен, что утечка памяти не допускается....   -  person Bryan Chen    schedule 27.03.2014
comment
Да, STL меня еще не подводил.   -  person Qaz    schedule 27.03.2014
comment
Хммм, emplace должно означать emplace, не так ли? ИМХО вряд ли что-то утечет.   -  person πάντα ῥεῖ    schedule 27.03.2014
comment
вы можете легко проверить это, войдя в конструктор/деструктор   -  person Bryan Chen    schedule 27.03.2014


Ответы (2)


Он вообще не должен создавать объект, но обычно он все равно будет (конечно, с использованием libstd++); технически это ошибка, но больше в стандарте, чем что-либо еще.

Более подробные сведения можно найти в предыдущем моем ответе на очень похожий вопрос:

person Lightness Races in Orbit    schedule 27.03.2014
comment
Если он не создает объект, как он может проверить, существует ли этот объект в наборе? Я прочитал ваш ответ на другой вопрос и связанное обсуждение isocpp, и я не понимаю, как это связано. В обсуждении вы, кажется, говорите о построении части значения пары ключ/значение карты. Речь идет о построении ключа, и я не вижу, как этого можно избежать (но очень заинтересован в том, чтобы его показали). - person Benjamin Lindley; 27.03.2014
comment
Я оспариваю ваше утверждение о том, что emplace требуется не создавать объект, когда вставка не удалась. Формулировка Вставляет [объект], созданный из [материала], тогда и только тогда, когда [условия], это не Конструкты и вставляет [объект] из [материала], если и только если [условия]. Использование прошедшего времени для сконструированного и настоящего времени для вставок указывает на то, что такая конструкция обязательно должна была иметь место до проверки условий и возможной вставки. - person Casey; 27.03.2014
comment
Формулировка, безусловно, могла бы быть более ясной, но ваше заявление об ошибке в некоторых версиях GCC подразумевает, что формулировка ясна и что libstdc++ не соответствует требованиям, что, я думаю, мы можем, по крайней мере, согласиться, что это не так. Учитывая возможность специализации std::pair, легко показать, что определение ключа конструируемого объекта из аргументов emplace в общем случае неразрешимо. Я не думаю, что стандарт может разумно требовать реализации, чтобы всегда избегать конструкции, когда вставка не выполняется. - person Casey; 27.03.2014
comment
@BenjaminLindley: Надеялись, что для сравнения будет создан только ключ, а не все отображаемое значение. Я соглашусь, что ограничение стандарта кажется неразрешимым, но я утверждаю, что именно об этом ясно говорится в текущей формулировке. - person Lightness Races in Orbit; 27.03.2014
comment
(^ в случае карт, во всяком случае) - person Lightness Races in Orbit; 27.03.2014
comment
Очевидным решением было бы создание компаратора, который принимает аргументы для пересылки в конструктор, а не реальный сконструированный объект. Однако я не вижу ничего подобного в документах. - person Chris; 21.02.2016

Из § 23.2.4 Таблица 102 — Требования к ассоциативному контейнеру (в дополнение к контейнеру)

emplace(args)

Эффекты: Вставляет объект value_type t, созданный с помощью std::forward<Args>(args)..., тогда и только тогда, когда в контейнере нет элемента с ключом, эквивалентным ключу t.

person user657267    schedule 27.03.2014