在显式调用析构函数时,它会被执行两次。这是什么原因?
#include <iostream>
using namespace std;
class A
{
public:
int x;
A() { cout << "A's constructor called " << endl; }
~A(){
cout<<"A's desctructor called "<<endl;
}
};
int main()
{
A a;
A b;
a.~A();
}
输出:
一个名为
的析构函数
的构造函数 一个名为
的析构函数 一个叫做
答案 0 :(得分:6)
好吧,你把它称之为'a',然后'语言'在对象超出范围时再次调用'a'。然后,当然,'语言'称之为b。当然,“语言”是指自动范围对象在其范围初始化时被构造并在范围结束时被破坏的非常基本的规则。
使用对析构函数的显式调用很少是一个好主意。
答案 1 :(得分:5)
你不应该手动调用析构函数,当对象超出范围时会自动调用它。
手动调用析构函数的唯一地方是当你编写自己的分配器时,但这是一个非常高级的主题,所以经验法则是永远不要手工调用析构函数。
答案 2 :(得分:3)
[basic.life] / 8:
如果某个程序使用[...]结束
T
类型对象的生命周期 自动(3.7.3)存储持续时间以及T
是否具有非平凡性 析构函数,程序必须保证原始对象 类型在隐式析构函数时占用相同的存储位置 调用发生; 否则程序的行为未定义。
因此我们无法解释一般程序的行为,但我们可以说&#34;对于您的实现,特定执行的行为就像析构函数被调用两次一样。&#34;
答案 3 :(得分:1)
当变量超出范围时,会隐式调用其析构函数。
如果那里没有相应类型的对象,则行为未定义。通常,编译器生成的代码会调用析构函数并盲目地执行,因为这会使得定义的行为成为可能。路径高效而简单,以及“未定义的行为”。路径被认为是你的错。
所以你所看到的是未定义行为的症状。您对析构函数的调用不意味着编译器不会尝试销毁该对象。
事实上,如果你的对象稍微复杂一点,很容易导致崩溃。
不要直接调用对象的析构函数,除非你使用了新的(new
的变体来构造一个对象并且没有分配任何内存)或等价物,并且不要使用#39除非你真的知道自己在做什么,否则请使用新的位置。
还有另一个有效的用途,你在同一个地方进行破坏和重建,但这很危险,通常是一个坏主意,很难做对。