【问题标题】:How to delete object constructed via placement new operator?如何删除通过放置新运算符构造的对象?
【发布时间】:2011-10-07 12:11:03
【问题描述】:
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的正确方法是什么?

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

【问题讨论】:

  • 您应该使用 T *t = new (buf) T: 而不是 T *t = (T*)buf;。这使您可以避免看起来可疑的演员表(所有演员表都是可疑的,但特别是这个,因为在大多数情况下,从char* 转换为T* 将违反别名。)

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


【解决方案1】:

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

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

C++ 标准:5.4.2

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

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

【讨论】:

  • 迟到的问题,但是如果你只是释放内存而不破坏对象会发生什么?
【解决方案2】:

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

t->~T();

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

delete []buf;

【讨论】:

    【解决方案3】:

    调用析构函数

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

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

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

      • 大家好,这个答案是真的吗?调用t 的析构函数时是否会释放缓冲区。如果是,那么我该如何避免它(即仅破坏*t,但保留缓冲区内存以再次分配一些对象)?
      • @Mihran,可能你误解了我的回答:我已经在说,The memory was actually allocated using char*; which you are properly freeing using delete[]。需要为t->~T() 调用析构函数,不需要delete t; 你必须在做delete[] buf; 你已经正确地做。
      猜你喜欢
      • 2016-11-05
      • 2015-06-24
      • 2020-01-27
      • 1970-01-01
      • 2012-07-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多