【发布时间】:2011-03-05 01:10:47
【问题描述】:
这个程序是否定义明确,如果没有,为什么?
#include <iostream>
#include <new>
struct X {
int cnt;
X (int i) : cnt(i) {}
~X() {
std::cout << "destructor called, cnt=" << cnt << std::endl;
if ( cnt-- > 0 )
this->X::~X(); // explicit recursive call to dtor
}
};
int main()
{
char* buf = new char[sizeof(X)];
X* p = new(buf) X(7);
p->X::~X(); // explicit call to dtor
delete[] buf;
}
我的推理:虽然invoking a destructor twice is undefined behavior,根据 12.4/14,它的确切含义是这样的:
如果 为对象调用析构函数 谁的生命已经结束了
这似乎并没有禁止递归调用。当对象的析构函数正在执行时,对象的生命周期还没有结束,因此再次调用析构函数不是 UB。另一方面,12.4/6 说:
在执行主体 [...] 之后 X 类的析构函数调用 X 的直接成员的析构函数, X 直接基数的析构函数 类 [...]
这意味着从递归调用析构函数返回后,所有成员和基类析构函数都将被调用,并且在返回上一级递归时再次调用它们将是UB。因此,没有基类且只有 POD 成员的类可以在没有 UB 的情况下具有递归析构函数。我说的对吗?
【问题讨论】:
-
这真的很奇怪,你为什么要调用递归的析构函数?
-
你为什么要这么做?
-
@Andrey 和 DeadMG:这主要是假设性的。随便阅读一下标准,就可以看出所有函数都可以递归调用,除了 main() (
§5.2.2/9),但看起来没那么简单。 -
@Cubbi:“随意阅读标准……”套用 Lisa Simpson (snpp.com/episodes/2F13.html) 的话说,我知道这些话,但那句话对我来说毫无意义。
-
这取决于你所说的“递归”。如果您看到对二叉树(包含指向 BinaryTree* leftSon 和 BinaryTree* rightSon 的指针的 BinaryTree 类)的遍历是递归的,那么它的析构函数也是递归的 :) 并且是的,它工作正常。
标签: c++ destructor standards-compliance