这个程序定义是否明确,如果没有,到底为什么?
#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;
}
我的推理:虽然调用析构函数两次是未定义的行为 https://stackoverflow.com/questions/2771567/why-exactly-is-calling-the-destructor-for-the-second-time-undefined-behavior-in-c,根据 12.4/14,它的确切内容是这样的:
该行为是未定义的,如果
为对象调用析构函数
谁的生命已经结束
这似乎并没有禁止递归调用。当对象的析构函数正在执行时,该对象的生命周期尚未结束,因此再次调用析构函数并不是UB。另一方面,12.4/6 说:
执行主体后 [...]
X 类的析构函数调用
X 的直接成员的析构函数,
X 直接基的析构函数
课程 [...]
这意味着从析构函数的递归调用返回后,所有成员和基类析构函数都将被调用,并且当返回到上一级递归时再次调用它们将是UB。因此,没有基类且只有 POD 成员的类可以具有没有 UB 的递归析构函数。我对吗?
答案是否定的,因为 §3.8/1 中“生命周期”的定义:
类型对象的生命周期T
结束时间:
— if T
是具有非平凡析构函数的类类型 (12.4),析构函数调用开始,或者
— 对象占用的存储被重用或释放。
一旦析构函数被调用(第一次),对象的生命周期就结束了。因此,如果您从析构函数内调用对象的析构函数,则根据第 12.4/6 节,行为是未定义的:
如果为生命周期已结束的对象调用析构函数,则行为未定义
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)