Новый (& * p) двойной;нет оп. Таким образом, uninitialized_default_construct также становится недоступным? - PullRequest
0 голосов
/ 04 октября 2019

Документация STL гласит, что (1) uninitialized_default_construct вызывает ::new (static_cast<void*>(std::addressof(*p))) Value;.

Единственная разница с (2) uninitialized_value_construct заключается в том, чтопоследующие звонки ::new (static_cast<void*>(std::addressof(*p))) Value();. (обратите внимание на ())

Интересно, в чем практическая разница как для встроенных, так и для нетривиальных типов.

Для встроенных модулей мне кажется, что second (2) выполнит инициализацию значения, т.е. установит значение в ноль, а first (1) будет неактивным (оставляя значение неинициализированным.)

Для нетривиальных типов (2) будем вызывать конструкторы по умолчанию. Что мне не понятно, так это то, что (1) будет делать для нетривиальных типов. Также вызовет конструктор по умолчанию? будет ли он также неактивным, пока T::T() = default, и он неактивен и оставит элемент в частично сформированном состоянии, если класс был спроектирован таким образом?

Что такжеменя смущает то, что контейнеры STL всегда будут использовать uninitialized_value_construct, хотя было бы более последовательным вызывать uninitialized_default_construct, когда это возможно.

Например, std::vector<double>(100) -> должен вызывать uninitialized_default_construct, в то время кактекущее поведение могло быть имитировано с помощью std::vector<double>(100, {}) или std::vector<double>(100, double{}).

Это потому, что концепция uninitialized_default_construct не существовала в начальной версии STL? или просто нет простого способа передать информацию в конструктор контейнера?

1 Ответ

2 голосов
/ 04 октября 2019

Меня также смущает то, что контейнеры STL всегда будут использовать uninitialized_value_construct, хотя было бы более логичным вызывать uninitialized_default_construct, когда это возможно.

Контейнеры не используют ни один. Контейнеры строят объекты через свои распределители. К сожалению, allocator_traits<...>::construct принимает произвольный ряд параметров. Передача без параметров неоднозначна между инициализацией по умолчанию и инициализацией значения. Какой из них использовать, зависит от распределителя, но нет способа выбрать, какой из них через список параметров. Значение по умолчанию allocator_traits::construct будет использовать инициализацию значения, и оно всегда будет делать это для всех типов.

текущее поведение могло быть имитировано с std::vector<double>(100, {})

Evenигнорируя проблемы обратной совместимости, а также материал, который я только что сказал о распределителях, этот конструктор означает «создать по умолчанию double и затем скопировать значение double в 100 элементов по одному за раз». Так что это не будет "текущим поведением".

...