为什么不在C++中调用Destructor

Why not call Destructor in C++?

本文关键字:调用 Destructor C++ 为什么不      更新时间:2023-10-16

我研究了C++的概念。我混淆了构造函数和析构函数的概念。从程序中退出时,编译器将隐式调用析构函数。但在我的程序中,只有构造函数调用了。

#include <iostream>
using namespace std;
class A
{
int i;
public:
A()
{
cout<<"Constructor call"<<endl;
}
~A()
{
cout<<"Destructtor call"<<endl;
}
};
int main()
{
A *a = new A();
}

输出:

Constructor call

所以,我有一个问题:为什么析构函数在退出程序时不被编译器隐式调用

为什么析构函数在退出程序时不被编译器隐式调用?

因为动态分配的对象不会自动销毁。这就是指定语言的方式。跟踪动态对象的销毁将需要运行时/内存开销。

解决方案:不要泄漏动态分配的对象。

C++中有两种"类型"的变量生存期。动态和自动。

自动是类似于:

void foo()
{
int i; // automatic storage
} // destroys i

这里,i在离开作用域的那一刻(在foo返回之后)将被销毁。你可以通过让你的对象有一个自动的生命周期来检查这一点:

int main()
{
A a; // calls A's constructor and allocates memory.
} //calls A's destructor and frees the memory used.

您将看到构造函数和析构函数都将被调用。


第二种形式是动态分配内存。您可以使用new动态分配内存(就像您所做的那样),并使用delete释放内存。编译器不会为您执行此操作。这意味着,要销毁对象,您必须自己显式调用delete

int main()
{
A* a = new A();
delete a; // calls A's destructor and frees the memory used.
}

如果你不调用delete(就像你的代码一样),那么程序离开main的那一刻,指针a就被破坏了,现在我们有一块没有东西可以访问的内存,因此没有人可以清理(使用delete),这意味着你正在泄漏内存。

然而,现代操作系统会在程序结束的那一刻自动回收程序使用的所有内存,所以在这一点上它不会太重要。这意味着你的析构函数不会像你刚才看到的那样被调用。


动态分配的内存允许您执行一些巧妙的技巧,例如控制对象的生存期,使其达到您想要使用delete显式销毁它们的程度。使用newdelete的问题是,很容易忘记一个delete,并且您的程序已经泄漏了内存,这就是为什么建议远离这种分配方式。

如果出于某种原因,您绝对需要动态生存期,那么使用像std::unique_ptr这样的智能指针,它会在超出范围时为您调用newdelete

使用new动态创建对象。只有当使用delete删除对象时,才会调用析构函数。

为了防止内存泄漏,您可以/应该使用像unique_ptr这样的智能指针。

在任何情况下,当进程结束时,内存本身当然会被释放。

在代码中永远不会调用析构函数,因为对象永远不会被破坏。

您可以动态分配A对象,但从不解除分配。将delete a;添加到main()中,您将看到析构函数在起作用:

int main()
{
A *a = new A();
delete a;
return 0;
}

在主函数中,您创建了一个指针变量,必须在主函数末尾的delete a将其删除。

因为内存泄漏。您动态创建了一个具有new的对象,并承诺将管理该对象的生存期,稍后使用delete对其进行清理。然后你违背了承诺。

如果你以通常的方式创建一个对象:

A a;

那么它会自动为你销毁。