在为对象调用析构函数时,它被调用两次
On calling destructor for an object, it is called two times?
显式调用desctructor时,它会执行两次。这是什么原因呢?
#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();
}
输出:
A 的构造函数称为
A的解构器称为
A的解构器称为
好吧,你用"a"调用它,然后当对象超出范围时,"语言"再次调用它为"a"。然后,当然,"语言"称它为b。当然,我所说的"语言"是指最基本的规则,即自动作用域对象在其作用域初始化时构造,并在作用域结束时析构。
对析构函数使用显式调用很少是一个好主意。
你不应该手动调用析构函数,当对象超出范围时,它会自动调用。
手动调用析构函数的唯一位置是编写自己的分配器时,但这是一个相当高级的主题,因此经验法则是永远不要手动调用析构函数。
[basic.life]/8:
如果程序使用 [...] 结束类型
T
对象的生存期 自动 (3.7.3( 存储持续时间,如果T
具有非平凡 析构函数,程序必须确保一个对象的原始 类型在隐式析构函数时占用相同的存储位置 通话发生;否则,程序的行为是未定义的。
因此,我们无法解释程序的一般行为,但我们可以说"对于您的实现,特定的执行行为就像析构函数被调用了两次一样。
当变量超出范围时,将隐式调用其析构函数。
如果那里没有适当类型的对象,则行为是未定义的。 通常,编译器生成的代码将调用析构函数并盲目地这样做,因为这会使"定义的行为"路径高效而简单,而"未定义的行为"路径被认为是您的错。
所以你所看到的是未定义行为的症状。 调用析构函数并不意味着编译器不会尝试销毁对象。
事实上,如果你的对象稍微复杂一些,它很容易导致崩溃。
不要直接调用对象的析构函数,除非您使用了放置 new(构造对象但不分配任何内存的 new
变体(或等效项,并且不要使用 place new,除非您真的知道自己在做什么。
还有另一种有效的用途,即在同一个地方破坏和重建,但这是危险的,通常是一个坏主意,而且很难正确。
- 从具有按值捕获的 lambda 移动构造 std::函数时,移动构造函数调用两次
- C++析构函数调用两次,堆栈分配的复合对象
- 对于优化级别为 0 的 std::vector,析构函数被调用两次
- 为什么这个自定义分配器的析构函数在 GCC/MSVS 的 stdlib 中被调用两次
- 重载运算符 new(),为什么构造函数被调用两次?
- 当 reset() 被unique_ptr调用两次时会发生什么?
- CEdit 框的NM_KILLFOCUS被调用两次
- 为什么这个构造函数被调用两次
- 析构函数在与 STL 的共享指针中调用两次
- 构造函数在不同线程中的静态单例类上调用两次
- 类析构函数在创建shared_ptr时调用两次
- 为什么在 C++ 中,当对象包含在另一个对象中时,复制构造函数被调用两次
- makefile 需要调用两次
- [c++]为什么我的类析构函数被调用两次?
- 为什么这个程序中的析构函数被调用两次
- 显式调用析构函数时被调用两次
- C++11 std::generate 和 std::uniform_real_distribution 调用两次会产生
- 基类函数被调用两次
- 为什么析构函数被调用两次,而构造函数只被调用一次
- 为什么函子的 dtor 在作为函数的参数传递给线程时调用两次(多次)