std::destroy_at
обеспечивает два объективных улучшения по сравнению с прямым вызовом деструктора:
Это уменьшает избыточность:
T *ptr = new T;
//Insert 1000 lines of code here.
ptr->~T(); //What type was that again?
Конечно, мы все предпочли бы просто обернуть его в unique_ptr
и покончить с этим, но если это не может произойти по какой-то причине, вставка T
является элементом избыточности. Если мы изменим тип на U
, нам придется изменить вызов деструктора, иначе все сломается. Использование std::destroy_at(ptr)
устраняет необходимость изменять одно и то же в двух местах.
СУХОЙ это хорошо.
Это легко:
auto ptr = allocates_an_object(...);
//Insert code here
ptr->~???; //What type is that again?
Если мы вывели тип указателя, то удалить его становится довольно сложно. Вы не можете сделать ptr->~decltype(ptr)()
; так как анализатор С++ так не работает. Мало того, decltype
выводит тип как указатель, поэтому вам нужно будет удалить косвенное указание указателя из выведенного типа. Приводит вас к:
auto ptr = allocates_an_object(...);
//Insert code here
using delete_type = std::remove_pointer_t<decltype(ptr)>;
ptr->~delete_type();
И кто хочет напечатать это?
Напротив, ваше гипотетическое std::construct_at
не обеспечивает целевых улучшений по сравнению с new
. Вы должны указать тип, который вы создаете в обоих случаях. Параметры конструктору должны быть предоставлены в обоих случаях. Указатель на память должен быть предоставлен в обоих случаях.
Так что нет нужды решать ваш гипотетический std::construct_at
.
И он объективно менее эффективен, чем новое размещение. Ты можешь это сделать:
auto ptr1 = new(mem1) T;
auto ptr2 = new(mem2) T{};
Это другие. В первом случае объект инициализируется по умолчанию, что может оставить его неинициализированным. Во втором случае объект инициализируется значением.
Ваш гипотетический std::construct_at
не может позволить вам выбрать тот, который вы хотите. Он может иметь код, который выполняет инициализацию по умолчанию, если вы не укажете никаких параметров, но тогда он не сможет предоставить версию для инициализации значения. И он может инициализировать значение без параметров, но тогда вы не сможете инициализировать объект по умолчанию.
Обратите внимание, что C++20 добавил std::construct_at
. Но это было сделано по причинам, отличным от согласованности. Они предназначены для поддержки выделения и построения памяти во время компиляции.
Вы можете вызвать заменяемые глобальные операторы new
в постоянном выражении (если вы фактически не заменили его). Но Placement-new не является заменяемой функцией, поэтому вы не можете вызвать ее там.
Предыдущие версии предложения о распределении constexpr полагались на std::allocator_traits<std::allocator<T>>::construct/destruct
. Позже они перешли к std::construct_at
в качестве функции построения constexpr
, на которую будет ссылаться construct
.
Таким образом, construct_at
был добавлен, когда можно было обеспечить объективные улучшения по сравнению с новым размещением.
person
Nicol Bolas
schedule
24.10.2018
destroy_at
;) - person 463035818_is_not_a_number   schedule 24.10.2018std::string
? Не поймите меня неправильно, я не говорю, что это невозможно, я просто хочу, чтобы вы ярко представили требуемое выражение лица. - person StoryTeller - Unslander Monica   schedule 24.10.2018auto s = new string{"test"}; s->~string();
? Я пропустил предпосылку вопроса? Я предполагаю, что вызов псевдодеструкторов для типов составных шаблонов был бы синтаксическим кошмаром, ноtypedef
достаточно. Решает лиdestroy_at
те же проблемы, что иmake_*
обертки? - person luk32   schedule 24.10.2018std::string
. - person StoryTeller - Unslander Monica   schedule 24.10.2018make_Stuff
обертки вокруг c'tors, да? - person luk32   schedule 24.10.2018~string()
. Вам нужно будет вызватьs->~basic_string();
.std::destroy_at(s);
в порядке. - person Daniel Langr   schedule 24.10.2018using namespace std;
. В противном случае вы не можете написать что-то какs->~std::string();
или, по крайней мере, компиляторы это не скомпилируют (см., например, здесь: stackoverflow.com /q/24593942/580083 для соответствующего обсуждения). Вот гдеstd::destroy_at
помогает. - person Daniel Langr   schedule 24.10.2018construct_at
:) (Это для усилий по контекстуализации контейнера.) - person T.C.   schedule 24.10.2018