Является ли вызов delete в результате удаления размещения, в котором использовался оператор, новым, хорошо?

Если я сделаю

struct MyStruct { ~MyStruct() { } };

void *buffer = operator new(1024);
MyStruct *p = new(buffer) MyStruct();
// ...
delete p;     //    <---------- is this okay?

это delete гарантированно позаботится о и то и другое призвание ~MyStruct() так же как operator delete?

12

Решение

delete p эквивалентно

p->~MyStruct();
operator delete(p);

если MyStruct имеет альтернативу operator deleteпоэтому ваш пример должен быть четко определен с ожидаемой семантикой.

[expr.delete]/2 состояния:

значение операнда удаления может быть … указатель на объект, не являющийся массивом, созданный предыдущим новое выражение.

Размещение нового типа новое выражение. [expr.new]/1:

новое выражение:
    ::выбирать новый новое размещениевыбирать new-type-id new-initializerвыбирать
    ::выбирать новый новое размещениевыбирать ( тип-идентификатор ) новый инициализаторвыбирать

delete определяется как вызов деструктора объекта, а затем вызов функции освобождения памяти. [expr.delete]/6,7:

удалить выражение вызовет деструктор (если есть) для объекта …

удалить выражение вызовет функцию освобождения …

Пока функция освобождения совпадает с функцией распределения (что и должно быть, если вы не перегружены operator delete для вашего класса), то все это должно быть четко определено.

13

Другие решения

[Пересмотрено] Это не совсем нормально, и вы можете только в целом delete то, что было получено с соответствующей равнине new выражение. В противном случае вы должны гарантировать, что функция освобождения соответствует функции распределения (поэтому использование ::delete p; было бы более безопасным общим решением, предполагая, что ваш оригинал operator new был в глобальном пространстве имен). В частности, когда рассматриваемый класс (или один из его производных классов) перегружается operator new ты должен быть осторожен.

Так как вы используете новое выражение для создания *pи поскольку не существует такого понятия, как «выражение размещения-удаления», необходимо уничтожить объект вручную, а затем освободить память:

p->~MyStruct();

operator delete(buffer);
12

Нет, обычно вы не должны вызывать delete (в некоторых случаях, например, когда оператор delete перегружен, это может быть нормально).

char *buffer = new char[1024];
MyStruct *p = new(buffer) MyStruct(); //placement new "i'm just calling constructor"p->~MyStruct();  //destroy the object.

//delete p; // WHAT? even if you override operator delete it may be opaque to reader.
delete [] buffer; // THIS DELETE IS OK (if you have first destroyed MyStruct)
0
По вопросам рекламы [email protected]