EXP*_*XP0 5 c++ destructor undefined-behavior
在我看来,下面的代码(来自一些C++问题)应该导致UB,但它似乎不是.这是代码:
#include <iostream>
using namespace std;
class some{ public: ~some() { cout<<"some's destructor"<<endl; } };
int main() { some s; s.~some(); }
Run Code Online (Sandbox Code Playgroud)
答案是:
some's destructor
some's destructor
Run Code Online (Sandbox Code Playgroud)
我学习了c ++ faq lite,我们不应该显式调用析构函数.我认为在显式调用析构函数后,应该删除对象s.程序完成后会自动再次调用析构函数,它应该是UB.但是,我在g ++上尝试了它,并获得与上述答案相同的结果.
是因为这个类太简单了(不涉及新的/删除)?或者在这种情况下它根本不是UB?
Jam*_*lis 15
行为未定义,因为析构函数被调用两次以用于同一对象:
在生命周期结束的对象上调用析构函数会导致每个C++03§12.4/ 6的未定义行为:
如果为生命周期结束的对象调用析构函数,则行为未定义
根据§3.8/ 1调用析构函数时,对象的生命周期结束:
类型对象的生命周期在以下情况
T结束:- 如果
T是具有非平凡析构函数(12.4)的类类型,则析构函数调用将启动,或者- 重用或释放对象占用的存储空间.
请注意,这意味着如果您的类有一个简单的析构函数,行为是明确定义的,因为这种类型的对象的生命周期不会结束,直到它的存储被释放,自动变量直到函数结束才会发生.当然,我不知道为什么你会明确地调用析构函数,如果它是微不足道的.
什么是琐碎的析构函数?§12.4/ 3说:
如果析构函数是一个隐式声明的析构函数,并且如果:
- 该类的所有直接基类都有微不足道的析构函数
- 对于类类的所有非静态数据成员(或其数组),每个这样的类都有一个简单的析构函数.
正如其他人所提到的,未定义行为的一个可能结果是您的程序似乎继续正常运行; 另一个可能的结果是你的程序崩溃了.任何事都可能发生,并且没有任何保证.
它是未定义的行为 - 但与任何UB一样,一种可能性是它(或多或少)似乎起作用,至少对于某些工作定义.
基本上,您需要(或想要)显式调用析构函数的唯一时间是与placement new结合使用(即,您使用placement new在指定位置创建对象,并使用显式dtor调用来销毁该对象).