Подтвердить что ты не робот

Как удалить объект, построенный с помощью нового оператора размещения?

char * buf = new char[sizeof(T)];
new (buf) T;
T * t = (T *)buf;
//code...
//here I should destruct *t but as it is argument of template and can be
//instantiated via basic types as well (say int) so such code 
/*t->~T();*/
//is incorrect (maybe correct? Strange, but it works on VS 2005 for basic types.)
//and this code 
/*delete t;*/ 
//crashes the program.
delete [] buf;

Итак, каков правильный способ разрушения t?

P.S. Приведенный выше код предназначен только для описания моей проблемы и не имеет реальных отношений с кодом, который я собираюсь написать. Поэтому, пожалуйста, не отвечайте на такие вопросы, как (зачем использовать размещение new вместо не размещения? Или что-то подобное)

4b9b3361

Ответ 1

... создается через базовые типы (скажем int), поэтому такой код
t->~T(); неверно...

Неправильно. Этот код является законным и правильным в коде шаблона, даже если T может быть примитивным типом.

Стандарт С++: 5.4.2

5.2.4 Вызов псевдодеструктора [expr.pseudo]

  • Использование псевдо-деструктор-имя после того, как оператор точки . или стрелка -> представляет деструктор типа non-class, названный именем типа. Результат должен использоваться только как операнд для вызова функции operator (), и результат такого вызова имеет тип void. Единственный эффект оценка постфиксного выражения перед точкой или стрелкой.
  • Левая часть оператора точки должна быть скалярного типа. Левый с правой стороны оператора стрелки должен быть указатель на скалярный тип. Этот скалярный тип является типом объекта. Тип, обозначенный псевдодвойство-имя должно быть таким же, как тип объекта. Кроме того, два имени типа в псевдоструктурированном имени форма ::opt nested-name-specifieropt type-name :: ˜ type-name должна обозначают один и тот же скалярный тип. Cv-безусловные версии тип объекта и тип, обозначенный псевдо-деструктором-именем должны быть одного и того же типа.

Ответ 2

Сначала вы уничтожите объект, вызвав его деструктор:

t->~T();

Затем вы уничтожаете память, вызывая delete[] по указателю, возвращенному из new[]:

delete []buf;

Ответ 3

Вызвать деструктор

T * t = (T *)buf;
t->~T();

затем освободите память с помощью delete[] buf. Вызов деструкторов явно - это точно, как это делается для объектов, созданных с помощью размещения new.

Ответ 4

Память была фактически распределена с помощью char*; , который вы правильно освобождаете, используя delete[] buf. Вам просто нужно вызвать деструктор t->~T() в этом случае для t. Нет необходимости delete t;.

Размещение new в этом случае используется только для создания объекта, а не для выделения памяти.