如何删除通过放置新运算符构造的对象?

时间:2011-07-18 08:37:55

标签: c++ templates new-operator destructor placement-new

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而不是非展示位置?或类似的东西)

4 个答案:

答案 0 :(得分:25)

  

... 也通过基本类型实例化(比如int)所以这样的代码   
t->~T();不正确
...

错误。即使T可以是基本类型,该代码在模板代码中也是合法且正确的。

C ++标准:5.4.2

  

5.2.4 伪析构函数调用[expr.pseudo]

     
      
  1. 使用a   点.或箭头->运算符表示后的伪析构函数名称   type-name命名的非类类型的析构函数。结果   只能用作函数调用operator ()的操作数,   并且这种调用的结果类型为void。唯一的影响是   在点或箭头之前评估后缀表达式。
  2.   
  3. 点运算符的左侧应为标量类型。左边   箭头操作符的手侧应为指向标量类型的指针。   此标量类型是对象类型。指定的类型   伪析构函数名称应与对象类型相同。   此外,伪结构中的两个类型名称   表格::opt nested-name-specifieropt type-name :: ˜ type-name   指定相同的标量类型。 cv不合格的版本   对象类型和伪析构函数名称指定的类型   应该是相同的类型。
  4.   

答案 1 :(得分:11)

首先通过直接调用析构函数来破坏对象:

t->~T();

然后通过调用delete[]返回的指针上的new[]来销毁内存:

delete []buf;

答案 2 :(得分:7)

调用析构函数

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

然后使用delete[] buf释放内存。显式调用析构函数正是如何使用展示位置new创建的对象。

答案 3 :(得分:3)

实际使用char*分配内存; 您正在使用 delete[] buf正确释放。在这种情况下,您只需要为t->~T()调用析构函数t。无需delete t;

在这种情况下,

放置 new仅用于构造不用于内存分配的对象。