【问题标题】:Calling destructors on new placement buffer?在新的放置缓冲区上调用析构函数?
【发布时间】:2015-05-17 04:14:12
【问题描述】:

所以我有这门课

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;
  }

这种使用“新”展示位置的方法是否有效?因为当我尝试删除地址时,没有调用析构函数。

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

  Obj * c = new(&buffer[0]) Obj;
  delete c;

谁能告诉我发生了什么?我真的必须删除指针才能调用析构函数吗?

【问题讨论】:

    标签: c++


    【解决方案1】:

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

    • 数组buffer 包含指向Obj 的指针。无法保证指针为对象提供足够的空间,或者指针正确对齐以容纳对象的对象。
    • 要销毁使用placement new 构造的对象,您需要一个类似于ptr-&gt;~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 类保护不同的缓冲区和对象以避免资源泄漏)。

    【讨论】:

    • 所以你使用了char*缓冲区来存储对象的地址?
    • 是的。这是跟踪对象缓冲区的位置。您也可以为所有对象使用一个缓冲区。
    • 我明白了,这很有帮助。非常感谢。
    • 不应该是objects[1] = new(&buffers[1]) Obj(); ?
    【解决方案2】:

    对于placement new,你必须直接调用析构函数。

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

    您必须对对象调用 delete,因为这将尝试释放内存。由于内存不是用 new 分配的,这是未定义的行为。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-04-06
      • 1970-01-01
      • 2011-02-28
      • 2011-05-24
      • 1970-01-01
      • 2011-04-23
      • 2014-12-10
      相关资源
      最近更新 更多