20
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呢?

PS 上面的代码只是为了描述我的问题,和我要写的代码没有真正的关系。所以请不要给出类似的答案(为什么使用安置new而不是非安置?或类似的东西)

4

4 回答 4

27

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

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

C++ 标准:5.4.2

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

  1. .在点或箭头运算符之后使用伪析构函数名称->表示由类型名称命名的非类类型的析构函数。结果只能用作函数调用的操作数operator (),并且这种调用的结果类型为 void。唯一的影响是对点或箭头之前的后缀表达式求值。
  2. 点运算符的左侧应为标量类型。箭头运算符的左侧应为指向标量类型的指针。此标量类型是对象类型。伪析构函数名称指定的类型应与对象类型相同。此外,表单的伪析构函数名称中的两个类型名称::opt nested-name-specifieropt type-name :: ˜ type-name应指定相同的标量类型。对象类型的 cv 非限定版本和由伪析构函数名称指定的类型应该是相同的类型。
于 2011-07-18T08:41:06.123 回答
12

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

t->~T();

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

delete []buf;
于 2011-07-18T08:41:25.530 回答
7

调用析构函数

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

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

于 2011-07-18T08:41:08.810 回答
3

内存实际上是使用char*;分配的 您正在使用 delete[] buf. t->~T()在这种情况下,您只需要调用析构函数即可t。没必要delete t;

在这种情况下放置 new,仅用于构造对象而不用于内存分配。

于 2011-07-18T08:43:40.787 回答