我有一个使用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...
}
自定义析构函数有什么缺点吗?
答案 0 :(得分:1)
虽然这在技术上是可行的,但我建议不要这样做。
析构函数有一个原因:编译器负责调用所有基类的析构函数。如果您使用自定义析构函数,则需要自己处理(并且可能会忘记它)。
此外,使用与默认析构函数不同的方法对于阅读代码的任何人来说都是显而易见的。
使用自定义析构函数有什么好处?我没有看到任何。
答案 1 :(得分: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...
}
这会调用自定义的“析构函数”和实际的析构函数,从而告诉编译器现在该对象不再存在。
答案 2 :(得分: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();