int main() {
Foo *leedle = new Foo();
return 0;
}
class Foo {
private:
somePointer* bar;
public:
Foo();
~Foo();
};
Foo::~Foo() {
delete bar;
}
析构函数会被编译器隐式调用,否则会出现内存泄漏问题吗?
我对动态内存分配不太熟悉,如果这不是一个可用的测试案例,我很抱歉。
int main() {
Foo *leedle = new Foo();
return 0;
}
class Foo {
private:
somePointer* bar;
public:
Foo();
~Foo();
};
Foo::~Foo() {
delete bar;
}
析构函数会被编译器隐式调用,否则会出现内存泄漏问题吗?
我对动态内存分配不太熟悉,如果这不是一个可用的测试案例,我很抱歉。
是的,自动变量将在封闭的代码块结束时被销毁。但请继续阅读。
您的问题标题询问当变量超出作用域时是否会调用析构函数。您可能想要询问的是:
Foo 在 main() 结束时会调用析构函数吗?
根据您提供的代码,该问题的答案为否,因为 Foo 对象具有动态存储期,我们很快就会看到。
请注意这里自动变量的定义:
Foo* leedle = new Foo();
在这里,leedle
是将被销毁的自动变量。 leedle
只是一个指针。 leedle
指向的东西没有自动存储期限,并且不会被销毁。 因此,如果你这样做:
void DoIt()
{
Foo* leedle = new leedle;
}
你泄漏了通过new leedle
分配的内存。
必须使用delete
删除任何已经使用new
分配的内存:
void DoIt()
{
Foo* leedle = new leedle;
delete leedle;
}
使用智能指针可以使这个过程变得更加简单和健壮。在 C++03 中:
void DoIt()
{
std::auto_ptr <Foo> leedle (new Foo);
}
或者在C++11中:
void DoIt()
{
std::unique_ptr <Foo> leedle = std::make_unique <Foo> ();
}
智能指针被用作自动变量,就像上面的例子一样。当它们超出范围并被销毁时,在析构函数中它们会自动(使用delete)删除指向的对象。因此,在上述两种情况下,都不会发生内存泄漏。
让我们试着澄清一下这里的一些术语。在C++中,变量拥有存储期。在C++03中,有三种存储期:
1:自动:具有自动存储期的变量将在封闭代码块的末尾被销毁。
考虑以下代码:
void Foo()
{
bool b = true;
{
int n = 42;
} // LINE 1
double d = 3.14;
} // LINE 2
在这个例子中,所有变量都具有自动存储期。 b
和 d
将在第2行被销毁。 n
将在第1行被销毁。
2:静态:具有静态存储期的变量将在程序开始之前分配,并在程序结束时被销毁。
3:动态:具有动态存储期的变量将在使用动态内存分配函数(例如new
)分配时分配,并在使用动态内存分配函数(例如delete
)销毁时销毁。
在我上面的原始示例中:
void DoIt()
{
Foo* leedle = new leedle;
}
leedle
是一个具有自动存储期的变量,将在结束大括号时销毁。 leedle
指向的东西具有动态存储期,在上面的代码中不会被销毁。您必须调用delete
来释放它。
C++11还添加了第四种存储期:
4: thread:具有线程存储期的变量在线程开始时分配,在线程结束时释放。
new
返回在堆上分配的对象的指针。你需要:int main() {
Foo *leedle = new Foo();
return 0;
}
new
使用动态存储分配对象而不是自动存储,所以它不会在函数结束时超出作用域。因此,它也不会被删除,导致内存泄漏。
new
创建的对象。如果您在构造函数中使用new
(并且没有抛出异常),则可以在析构函数中调用delete
,它会为您清理内存。 - Rapptz