在析构函数内部或外部放置删除

时间:2014-09-22 16:18:52

标签: c++

我在阅读放置新操作符时发现了以下代码。

#include <iostream>
using namespace std;

class MyClass {

public:
  // Placement new operator
  void* operator new (size_t sz, void* v) {
    cout << "Placement new invoked" << endl;
    return v;
  }

  ~MyClass() {
    // Cleanup
  }
};

int main()
{
    // Create a buffer to store the object
    int buffer[16];
    cout << "Starting address of my buffer = " << &buffer << endl;

    // Create the object. Use placement new
    MyClass* obj = new (buffer) MyClass();
    cout << "Location of my object = " << obj << endl;

    // Don't delete object created with placement delete
    // Call the destructor explicitly
    obj->~MyClass();
}

我几乎没有与使用placement new:

创建的删除对象相关的问题
  1. 什么是清理代码需要在析构函数中编写才能 在缓冲存储器中占用obj的空闲内存。
  2. 不需要定义放置删除,如果是,则需要在析构函数内部还是在析构函数外部。如果它在析构函数之外它将如何被调用?

3 个答案:

答案 0 :(得分:0)

  

什么是清理代码需要在析构函数中编写以释放缓冲内存中占用obj的内存

析构函数应该执行任何析构函数的操作:清理对象管理的所有资源。在这种情况下,它不管理任何资源,因此不需要做任何事情。

根据如何分配对象本身的存储空间,它不应该做任何特殊操作。在需要时,管理该存储是自定义newdelete运营商的工作。

  

不需要定义展示位置删除

没有。 Placement-new用于构建您自己管理的存储中的对象,您自己负责释放该存储。在这种情况下,存储是自动的,因此当函数退出时它会自动释放。

就像placement-new的分配器什么都不做(只是将提供的指针返回到预先分配的存储)一样,相应的deallocator什么都不做;所以它不存在。你只需要在自己处理存储之前直接调用它的析构函数来销毁对象。

答案 1 :(得分:0)

常规new会做两件事:

  1. 为您的对象分配内存
  2. 在该内存空间中构建您的对象。
  3. 展示位置new表示您管理其中一个,另一个像以前一样进行管理。

    1. 您为对象分配/提供内存
    2. 在该内存空间中调用构造函数。
    3. 反之为delete,常规delete执行以下操作:

      1. 调用要清理的对象的析构函数
      2. 释放为其分配的内存。
      3. 请注意,出于显而易见的原因,它们以相反的顺序完成。您无法释放包含有关需要清理的内容的信息的内存,即使您已完成使用该内存。而在构造中,你需要先掌握记忆。

        在你所谓的贴片删除中,但实际上与贴片新位置相反,你需要执行破坏的第一步而不是第二步。因此,您调用对象的析构函数,然后您可以释放它使用的内存/将其用于其他内容。

        使用placement new的最常见示例是std::vector的实现,它需要一个连续的缓冲区用于其数据,并且允许您提前预订(如果不这样做,它可能会执行此操作)您)。该部分分配内存但不构造其中的对象。因此,当它们稍后构建时,将使用placement new。

答案 2 :(得分:0)

首先要问的是:你想做什么?如果你 在类中定义一个新的贴装操作符,然后就是 只有在编写new MyClass时才能找到的operator new;你必须总是指定额外的参数。并在 几乎在每个定义特定类operator new的情况下,您还应该定义一个特定类operator delete; 否则将调用全局operator delete函数 当你写delete p时,这通常是行不通的。

如果你的目标是系统地要求分离 分配和初始化,这就是你定义的原因 一个成员运营商new,然后你可以提供一个no-op operator delete;如果类的构造函数可以抛出,那么你就可以了 还希望提供一个放置操作符删除,因为这是 如果新对象的构造函数退出,将调用什么 通过例外。然而,没有其他方法可以称之为。 提供新的展示位置运算符时,您必须提供 一个默认的运算符delete,它做了正确的事;什么时候 您需要为同一类型提供多个新操作员 在每个分配中以某种方式记住哪个被称为 命令在非放置运算符中分派删除。

顺便说一下,只需将缓冲区分配为局部变量 保证足够的对齐除了 声明缓冲类型。

编辑:

只是operator delete函数(必须是成员)所需内容的示例:

void operator delete( void* p ) {}
void operator delete( void* p, void* ) {}