1

我有一个使用placement new分配的对象。当不再需要该对象时,我显式地使用它的析构函数,然后自己处理内存,如网络上的各种资源中所述。

但是,我不清楚编译器是否可以为析构函数调用生成任何额外的“后台魔法”,而不仅仅是为析构函数内部的内容生成指令。实际的问题是:在“placement-new”的情况下,有什么会阻止我使用“自定义析构函数”而不是常规(〜语法)析构函数?简单的类方法,包含所有常用的析构函数代码,但可能额外接受参数。

这是一个例子:

class FooBar {
  FooBar() { ... }
  ...
  void myCustomDestructor(int withArguments) { ... }
  ...
};

int main() {
  ...
  FooBar* obj = new (someAddress) FooBar();
  ...
  obj->~FooBar();  // <- You're supposed to do this.
  obj->myCustomDestructor(5);  // <- But can you do this instead?
  ...
  // Then do whatever with the memory at someAddress...
}


自定义析构函数有什么缺点吗?

4

3 回答 3

1

虽然这在技术上是可行的,但我建议不要这样做。

析构函数的存在是有原因的:编译器负责调用所有基类的析构函数。如果您使用自定义析构函数,则需要自己处理(并且可能会在某处忘记它)。

此外,使用与默认析构函数不同的方法对于阅读您的代码的任何人来说都是显而易见的。

您期望使用自定义析构函数有什么好处?我没有看到。

于 2013-02-13T00:55:06.383 回答
1

“额外的魔法”是对象仅在调用析构函数后才停止存在。所以你不能在调用后重用内存,myCustomDestructor因为对象“仍然存在”,好吧,至少没有未定义的行为。

一种解决方案是制作一个私有析构函数并执行以下操作:

class FooBar {
  public:
    FooBar() { ... }
    static void destruct(FooBar& foobar, int withArguments) {
       foobar.myCustomDestructor(withArguments);
       foobar.~FooBar();
    }
  private:
    void myCustomDestructor(int withArguments) { ... }
    ~FooBar() {}
};

int main() {
  ...
  FooBar* obj = new (someAddress) FooBar();

  FooBar::destruct(*obj, 5);

  // Then do whatever with the memory at someAddress...
}

这会调用自定义的“析构函数”和实际的析构函数,从而告诉编译器该对象现在不再存在。

于 2013-02-13T00:57:55.423 回答
1

不,如果没有未定义的行为,您将无法做到这一点。我会这样做:

void FooBar::prepareForCustomDestruction(int arguments)
{
    do_custom_destruction = true;
    custom_destructor_arguments = arguments;
}

FooBar::~FooBar()
{
    if (do_custom_destruction)
    {
        // custom destruction
    }
    else
    {
        // normal destruction
    }
}

然后如果你想模拟调用自定义析构函数,只需prepareForCustomDestruction先调用。

obj->prepareForCustomDestuction(5);
obj->~FooBar();
于 2013-02-13T01:09:55.277 回答