C++ 当对象超出范围时是否调用析构函数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17702936/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is a destructor called when an object goes out of scope?
提问by Tux
For example:
例如:
int main() {
Foo *leedle = new Foo();
return 0;
}
class Foo {
private:
somePointer* bar;
public:
Foo();
~Foo();
};
Foo::~Foo() {
delete bar;
}
Would the destructor be implicitly called by the compiler or would there be a memory leak?
析构函数会被编译器隐式调用还是会出现内存泄漏?
I'm new to dynamic memory, so if this isn't a usable test case, I'm sorry.
我是动态内存的新手,所以如果这不是一个可用的测试用例,我很抱歉。
回答by John Dibling
Yes, automatic variables will be destroyed at the end of the enclosing code block. But keep reading.
是的,自动变量将在封闭代码块的末尾被销毁。但继续阅读。
Your question title asks if a destructor will be called when the variable goes out of scope. Presumably what you meant to ask was:
您的问题标题询问当变量超出范围时是否会调用析构函数。想必你想问的是:
will Foo's destructor be called at the end of main()?
会在 main() 结束时调用 Foo 的析构函数吗?
Given the code you provided, the answer to that question is nosince the Foo object has dynamic storage duration, as we shall see shortly.
鉴于您提供的代码,该问题的答案是否定的,因为 Foo 对象具有动态存储持续时间,我们很快就会看到。
Note here what the automatic variable is:
请注意这里的自动变量是什么:
Foo* leedle = new Foo();
Here, leedle
is the automatic variable that will be destroyed. leedle
is just a pointer. The thing that leedle
points to does nothave automatic storage duration, and will not be destroyed. So, if you do this:
这里,leedle
是将被销毁的自动变量。 leedle
只是一个指针。leedle
指向的东西没有自动保存期限,不会被销毁。所以,如果你这样做:
void DoIt()
{
Foo* leedle = new leedle;
}
You leak the memory allocated by new leedle
.
你泄漏了分配的内存new leedle
。
You mustdelete
anything that has been allocated with new
:
您必须delete
已分配的任何内容new
:
void DoIt()
{
Foo* leedle = new leedle;
delete leedle;
}
This is made much simpler and more robust by using smart pointers. In C++03:
通过使用智能指针,这变得更加简单和健壮。在 C++03 中:
void DoIt()
{
std::auto_ptr <Foo> leedle (new Foo);
}
Or in C++11:
或者在 C++11 中:
void DoIt()
{
std::unique_ptr <Foo> leedle = std::make_unique <Foo> ();
}
Smart pointers are used as automatic variables, as above, and when they go out of scope and are destroyed, they automatically (in the destructor) delete
the object being pointed to. So in both cases above, there is no memory leak.
智能指针用作自动变量,如上所述,当它们超出范围并被销毁时,它们会自动(在析构函数中)delete
指向所指向的对象。所以在上述两种情况下,都没有内存泄漏。
Let's try to clear up a bit of language here. In C++, variables have a storage duration. In C++03, there are 3 storage durations:
让我们试着在这里澄清一些语言。在 C++ 中,变量具有存储持续时间。在 C++03 中,有 3 个存储持续时间:
1: automatic: A variable with automatic storage duration will be destroyed at the end of the enclosing code block.
1:自动: 具有自动存储期的变量将在封闭代码块的末尾被销毁。
Consider:
考虑:
void Foo()
{
bool b = true;
{
int n = 42;
} // LINE 1
double d = 3.14;
} // LINE 2
In this example, all variables have automatic storage duration. Both b
and d
will be destroyed at LINE 2. n
will be destroyed at LINE 1.
在这个例子中,所有变量都有自动存储持续时间。双方b
并d
会在第2行销毁 n
将在LINE 1被破坏。
2: static: A variable with static storage duration will be allocated before the program begins, and destroyed when the program ends.
2: static:一个具有静态存储期的变量会在程序开始前分配,在程序结束时销毁。
3: dynamic: A variable with dynamic storage duration will be allocated when you allocate it using dynamic memory allocation functions (eg, new
) and will be destroyed when you destroy it using dynamic memory allocation functions (eg, delete
).
3: dynamic:具有动态存储期的变量在使用动态内存分配函数(例如,new
)分配时将被分配,在使用动态内存分配函数(例如,)销毁时将被销毁delete
。
In my original example above:
在我上面的原始示例中:
void DoIt()
{
Foo* leedle = new leedle;
}
leedle
is a variable with automatic storage duration and will be destroyed at the end brace. The thing that leedle
points to has dynamic storage duration and is not destroyed in the code above. You must call delete
to deallocate it.
leedle
是一个具有自动存储持续时间的变量,将在大括号结束时销毁。leedle
指向的东西具有动态存储期,在上面的代码中没有被销毁。您必须调用delete
以解除分配它。
C++11 also adds a fourth storage duration:
C++11 还增加了第四个存储持续时间:
4: thread: Variables with thread storage duration are allocated when the thread begins and deallocated when the thread ends.
4:线程:具有线程存储期的变量在线程开始时分配,在线程结束时释放。
回答by Arne Mertz
Yes, if an object goes out of scope, the destructor gets called. BUTNo, the destructor won't be called in this case, because you only have a pointerin scope, that pointer has no particular destructor, so there will be no indirect call to Foo
's destructor.
是的,如果对象超出范围,则会调用析构函数。但是不,在这种情况下不会调用析构函数,因为范围内只有一个指针,该指针没有特定的析构函数,因此不会间接调用Foo
的析构函数。
This example is the application domain of smart pointers like std::unique_ptr
and std::shared_ptr
. Those are actual classes that, unlike raw pointers havea destructor, (conditionally) calling delete
on the pointed-to object.
这个例子是智能指针的应用领域,比如std::unique_ptr
和std::shared_ptr
。这些是实际的类,与原始指针不同,它们具有析构函数,(有条件地)调用delete
指向的对象。
Btw, Foo
's destructor deletes bar
, bur bar
has never been initialized nor assigned to an address that points to an actual object, so the delete call will give undefined behavior, likely a crash.
顺便说一句,Foo
的析构函数 deletes bar
, burbar
从未被初始化或分配给指向实际对象的地址,因此删除调用将给出未定义的行为,可能会导致崩溃。
回答by Stefano Falasca
there would be a memory leak indeed. The destructor for the object which goes out of scope (the Foo*) gets called, but the one for the pointed-to object (the Foo you allocated) does not.
确实会有内存泄漏。超出范围的对象(Foo*)的析构函数被调用,但指向对象(您分配的 Foo)的析构函数没有被调用。
Technically speaking, since you are in the main, it is not a memory leak, since you up to when the application is not terminated you can access every allocated variable. With this respect, I cite Alexandrescu (from Modern C++, the chapter about singletons)
从技术上讲,由于您在 main 中,因此它不是内存泄漏,因为在应用程序未终止之前,您可以访问每个分配的变量。在这方面,我引用了 Alexandrescu(来自现代 C++,关于单例的章节)
Memory leaks appear when you allocate accumulating data and lose all references to it. This is not the case here: Nothing is accumulating, and we hold knowledge about the allocated memory until the end of the application. Furthermore, all modern
当您分配累积数据并丢失对它的所有引用时,就会出现内存泄漏。这里的情况并非如此:没有任何东西在累积,我们一直持有有关已分配内存的知识,直到应用程序结束。此外,所有现代
Of course, this does not imply that you should not call delete
, as it would be an extremely bad (and dangerous) practice.
当然,这并不意味着您不应该调用delete
,因为这将是一种非常糟糕(且危险)的做法。
回答by Joni
First note that the code wouldn't compile; new
returns a pointer to an object allocated on the heap. You need:
首先要注意代码不会编译;new
返回一个指向在堆上分配的对象的指针。你需要:
int main() {
Foo *leedle = new Foo();
return 0;
}
Now, since new
allocates the object with dynamic storage instead of automatic, it's not going out of scope at the end of the function. Therefore it's not going to get deleted either, and you have leaked memory.
现在,由于new
使用动态存储而不是自动分配对象,它不会在函数结束时超出范围。因此它也不会被删除,并且您已经泄漏了内存。
回答by Scotty Bauer
In this instance, when main returns it's the end of the program, the Operating system will handle freeing all resources. If, for instance this was any other function, you would have to use delete.
在这种情况下,当 main 返回时,程序结束,操作系统将处理释放所有资源。例如,如果这是任何其他函数,则必须使用 delete。