在新的放置缓冲区上调用析构函数

Calling destructors on new placement buffer?

本文关键字:调用 析构函数 缓冲区      更新时间:2023-10-16

所以我有这个类

class Obj{           //simple class with constructor + destructor
  public:
  Obj(){cout<<"Obj1 has been created"<<endl;}
  ~Obj(){cout<<"Obj1 has been destroyed"<<endl;}
  };

  Obj * buffer[10];  //buffer

  int main(int argc, char *argv[])
  {
  Obj * c = new(&buffer[0]) Obj;
  delete &buffer[0];
  system("PAUSE");
  return EXIT_SUCCESS;
  }

这种使用位置"new"的方法是有效的吗?因为当我试图删除地址时,没有调用析构函数

但是如果我使用这行代码,析构函数将被调用

  Obj * c = new(&buffer[0]) Obj;
  delete c;
谁能告诉我发生了什么事?我真的必须删除指针才能调用析构函数吗?

在您的示例中使用位置new以及试图销毁它都是无效的:

  • 数组buffer包含指向Obj的指针。不能保证指针为对象提供足够的空间,也不能保证指针正确对齐以容纳对象的对象。
  • 要销毁用placement new构造的对象,你需要一个显式的析构函数调用,看起来像ptr->~Obj()

正确的位置设置应该是这样的:

Obj*  objects[10];
char* buffers[10];
// ...
buffers[1] = new char[sizeof(Obj)];
objects[1] = new(buffers[1]) Obj();
// ...
objects[1]->~Obj();
delete[] buffers[1];

(显然,在实际代码中,您将通过合适的RAII类来保护不同的缓冲区和对象,以避免资源泄漏)。

使用new位置时,必须直接调用析构函数。

buffer[0].~Obj();
// or
c->~Obj();

你必须NOT在对象上调用delete,因为这会尝试释放内存。由于内存没有分配new,这是未定义的行为。

// delete &buffer[0];  Don't do this.