为什么不在 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
明确销毁它们的程度。使用 new
和 delete
的问题是很容易忘记单个 delete
并且您的程序已经泄漏内存,这就是为什么建议远离这种分配方式的原因.
如果出于某种原因你绝对需要动态生命周期,那么使用像 std::unique_ptr
这样的智能指针,它会在它超出范围时为你调用 new
和 delete
。
我正在学习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
明确销毁它们的程度。使用 new
和 delete
的问题是很容易忘记单个 delete
并且您的程序已经泄漏内存,这就是为什么建议远离这种分配方式的原因.
如果出于某种原因你绝对需要动态生命周期,那么使用像 std::unique_ptr
这样的智能指针,它会在它超出范围时为你调用 new
和 delete
。