显式调用析构函数时被调用两次
Destructor being called twice when being explicitly invoked
我正在用这段代码在C++中试验析构函数:
#include <iostream>
struct temp
{
~temp() { std::cout << "Hello!" << std::endl; }
};
int main()
{
temp t;
t.~temp();
}
我看到"你好!"被打印了两次。析构函数的调用不应该释放对象,并且当析构函数超出范围时不应该再次调用它吗?还是有其他概念?
(我并不打算在实践中这样做。我只是想了解这里发生了什么。
它之所以发生,是因为你告诉它会发生。当变量超出范围时,始终调用自动变量的析构函数。你也叫它。总共是两个电话。
调用对象的析构函数不会发出信号,C++不再调用它,因为在正常执行中不需要跟踪。
解决方案是永远不要手动调用析构函数。
调用析构函数不会释放对象。
析构函数用于清理对象的内部,然后在析构函数完成后释放对象本身。
执行您正在执行的操作类似于在对象上调用 delete 两次的方式是错误的,但这样做是错误的。
只有极少数情况下,您希望手动调用析构函数,这不是其中之一。当您使用放置 new 在内存位置手动构造对象时,它确实存在,然后需要能够在不释放内存的情况下销毁它。
我看到"Hello!"被打印了两次。 析构函数的调用不应该释放对象,并且当析构函数超出范围时,不应该再次调用它。还是有其他概念?
没错。
我必须提到,我并不打算在实践中这样做。我只是想了解这里发生了什么。
您已经调用了析构函数,准备要销毁的对象。但是,当对象超出范围时,在实际取消分配之前,这也会自动完成。
要理解的是:如果你做了没有意义的事情,那么坏事就会发生。所以不要做没有意义的事情。如果手动调用析构函数,则析构函数将运行。这对其他任何事情都没有影响,除非析构函数实际执行了有影响的操作。
你只是调用析构函数,你实际上并没有释放任何内存(它是静态分配的)。如果使用 new 然后删除,则析构函数将只调用一次。
构函数是指在对象超出范围时调用的,如果对象在堆栈中,在这种情况下,或者当它被显式破坏时,当对象首先使用new运算符在堆上创建时
,则调用。编译器或运行时系统无法跟踪析构函数是否由您手动调用。此外,调用析构函数也是一种非常糟糕的做法。
如果您想在删除对象之前进行一些手动清理(除了从内存中删除或从堆栈中删除的对象),您可以执行以下操作。
在这里,您希望允许客户端手动清理内容,甚至在删除对象之前。但除此之外,如果客户错过清洁,您可以清洁东西。
class A
{
public:
A() : _closed(false)
{}
~A()
{
close();
}
void close()
{
if (! _closed()) {
// close file handles etc.
}
}
private:
bool _closed
}
构函数不是对象的"破坏者"。 它只是一个普通的函数,但它是由销毁时间之前的语言自动调用的。
它的正式名称是析构函数,但如果我们称它为"销毁前"函数,也许会更容易理解。
您不需要调用析构函数,尽管可以这样做。编译器应在不再使用对象时隐式运行析构函数。创建对象时,如果构造函数已使用类成员的特定值和初始化值声明,则将构造函数用于该对象。当您不再需要您的对象时,析构函数将运行并删除成员变量声明及其值。这对于不使用自动垃圾回收的语言(如C++)最有用。
您不会显式调用析构函数,当变量超出范围时会自动调用它(此处在 return 0;
语句之后)。这就是为什么它被调用两次,你调用它,然后系统调用它。
如果您希望能够自己显式删除此类的实例,则需要动态分配它:
temp *t = new temp;
// do stuff with t...
delete t; // do not forget this, or the constructor is not being called at all
你实际上不应该调用解构函数。运行时支持会为您调用它。因此,您调用它一次,运行时支持人员第二次调用它。
以下是一些关于析构函数的思考:
http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fcplr380.htm
您可以显式调用解构函数,但不建议这样做,通常隐式调用它们。
可以调用类的析构函数:
-
明确地
当使用类的对象显式调用析构函数时,调用类的另一个成员函数的方式相同。
-
隐 式
当类的对象超出范围或使用 new 运算符创建的对象被使用 delete 运算符销毁时。
在示例程序中,您可以同时执行这两项操作
int main()
{
temp t;
t.~temp(); //1. Calling destructor explictly using the object `t`
return 0;
} // 2. object `t` goes out of scope. So destructor invoked implictly
这就是为什么你看到析构函数被调用两次的原因。
正如您恰当地认为的那样,析构函数将破坏构造函数创建的资源。因此,不应明确调用destrutor,因为它将导致破坏已经破坏的资源,这可能是致命的。
- 从具有按值捕获的 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 在作为函数的参数传递给线程时调用两次(多次)