为什么不在 C++ 中调用析构函数?

Why not call Destructor in C++?

我正在学习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

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

Why destructor not call implicit by the compiler upon exit program?

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

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

您使用 new 动态创建对象。只有在使用 delete.

删除对象时才会调用析构函数

为了防止内存泄漏,您 could/should 使用智能指针,例如 unique_ptr

无论如何,内存本身当然会在进程结束时释放。

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

如果您以通常的方式创建对象:

A a;

那么会自动帮你销毁

您的代码中永远不会调用析构函数,因为对象永远不会被销毁。

您动态分配了 A 对象,但您从未取消分配它。将 delete a; 添加到 main() 中,您将看到正在运行的析构函数:

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

    return 0;
}

在您的 main 函数中,您创建了一个指针变量,您必须在 main 函数结束时通过 delete a 将其删除。

C++ 中有 2 "types" 个变量生命周期。动态和自动。

自动类似于:

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

在这里,i 将在离开作用域时被销毁(在 foo returns 之后)。您可以通过让您的对象具有自动生命周期来自行检查:

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),这意味着你是 leaking memory.

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


动态分配的内存允许你做一些巧妙的技巧,比如控制你的对象的生命周期到你想用 delete 明确销毁它们的程度。使用 newdelete 的问题是很容易忘记单个 delete 并且您的程序已经泄漏内存,这就是为什么建议远离这种分配方式的原因.

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