Ответ 1
std::vector
можно построить из std::initializer_list
, и вы вызываете этот конструктор. Правила для конструкции initializer_list утверждают, что этот конструктор агрессивно предпочтителен:
Конструктор - это конструктор списка инициализаторов, если его первый параметр имеет тип
std::initializer_list<E>
или ссылку на возможно cv-квалифицированныйstd::initializer_list<E>
для некоторого типаE
, и либо есть нет других параметров, иначе все остальные параметры имеют аргументы по умолчанию (8.3.6). [Примечание: список инициализаторов конструкторы предпочтительнее других конструкторов в инициализации списка <... > ]
Кроме того, из-за какой-то странной реализации initializer_list
в качестве массива, выделенного под капотом, элементы соответствующего массива, на которые ссылается std::initializer_list<E>
, принудительно инициализируются копией (которые могут быть удалены):
Объект типа
std::initializer_list<E>
строится из списка инициализаторов, как если бы реализация выделен массив элементовN
типаE
, гдеN
- количество элементов в списке инициализаторов. Каждый элемент этого массива инициализируется копией с соответствующим элементом списка инициализаторов и объектstd::initializer_list<E>
создается для обращения к этому массиву
(Обе приведенные выше ссылки из N3337 [dcl.init.list])
Однако в вашем первом примере копии могут/будут удалены, несмотря на имя ([dcl.init]/14), чтобы вы не увидели дополнительную конструкцию копии (их также можно переместить). Вы можете поблагодарить свой компилятор за что, поскольку копирование не требуется в С++ 11 (хотя оно находится на С++ 17).
Для получения дополнительной информации см. [class.copy] ("Когда определенные критерии выполнены, реализации разрешено опускать конструкцию копирования/перемещения класса объект... ").
Заключительная часть - ключ:
[support.initlist] указывает, что
Объект типа
initializer_list<E>
предоставляет доступ к массиву объектов типаconst E
.
Это означает, что std::vector
не может напрямую захватить память; он должен быть скопирован, вот где вы в конечном итоге видите, что вызываемые копии создаются.
Во втором примере, как указано в заявлении Kerrek SB, вы предотвратили упомянутое ранее копирование, и вызвали дополнительные накладные расходы.