当对象超出范围时,会调用析构函数吗?

时间:2022-09-25 18:52:48

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.

我刚接触动态内存,所以如果这不是一个可用的测试用例,对不起。

5 个解决方案

#1


80  

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()?

Foo的析构函数会在main()末尾被调用吗?

Given the code you provided, the answer to that question is no since the Foo object has dynamic storage duration, as we shall see shortly.

根据您提供的代码,这个问题的答案是no,因为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 not have 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.

您泄漏了由新leedle分配的内存。


You must delete anything that has been allocated with 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.

如上所述,智能指针被用作自动变量,当指针超出范围并被销毁时,它们将自动(在析构函数中)删除指向的对象。所以在上面的两种情况下,都没有内存泄漏。


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: automatic:一个具有自动存储量持续时间的变量将会在封闭代码块的末尾被销毁。

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将在第一行被毁灭。

2: static: A variable with static storage duration will be allocated before the program begins, and destroyed when the program ends.

2:静态:在程序开始之前分配一个具有静态存储时间的变量,在程序结束时销毁。

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:动态:当您使用动态内存分配函数(如新)分配时,将分配动态存储持续时间的变量,并在使用动态内存分配函数(如删除)时销毁它。

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:线程:当线程开始时分配具有线程存储时间的变量,当线程结束时分配释放变量。

#2


6  

Yes, if an object goes out of scope, the destructor gets called. BUT No, the destructor won't be called in this case, because you only have a pointer in scope, that pointer has no particular destructor, so there will be no indirect call to Foo's destructor.

是的,如果一个对象超出范围,就会调用析构函数。但是不,在这种情况下不会调用析构函数,因为在作用域中只有一个指针,这个指针没有特定的析构函数,所以不会间接调用Foo's析构函数。

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 have a 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的析构函数会删除bar,但是bar从来没有被初始化,也没有被分配到指向一个实际对象的地址,所以delete调用会给出未定义的行为,可能会导致崩溃。

#3


2  

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)

从技术上讲,由于您在主服务器中,所以它不是一个内存泄漏,因为当应用程序没有终止时,您可以访问每个已分配的变量。在这方面,我引用了亚历山大(来自现代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,因为这是一种极其糟糕(而且危险)的实践。

#4


1  

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用动态存储而不是自动存储分配对象,它在函数的末尾不会超出范围。因此它也不会被删除,而且你已经泄露了内存。

#5


-5  

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.

在此实例中,当主返回时它是程序的结束,操作系统将处理释放所有资源。例如,如果这是任何其他函数,则必须使用delete。

#1


80  

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()?

Foo的析构函数会在main()末尾被调用吗?

Given the code you provided, the answer to that question is no since the Foo object has dynamic storage duration, as we shall see shortly.

根据您提供的代码,这个问题的答案是no,因为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 not have 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.

您泄漏了由新leedle分配的内存。


You must delete anything that has been allocated with 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.

如上所述,智能指针被用作自动变量,当指针超出范围并被销毁时,它们将自动(在析构函数中)删除指向的对象。所以在上面的两种情况下,都没有内存泄漏。


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: automatic:一个具有自动存储量持续时间的变量将会在封闭代码块的末尾被销毁。

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将在第一行被毁灭。

2: static: A variable with static storage duration will be allocated before the program begins, and destroyed when the program ends.

2:静态:在程序开始之前分配一个具有静态存储时间的变量,在程序结束时销毁。

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:动态:当您使用动态内存分配函数(如新)分配时,将分配动态存储持续时间的变量,并在使用动态内存分配函数(如删除)时销毁它。

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:线程:当线程开始时分配具有线程存储时间的变量,当线程结束时分配释放变量。

#2


6  

Yes, if an object goes out of scope, the destructor gets called. BUT No, the destructor won't be called in this case, because you only have a pointer in scope, that pointer has no particular destructor, so there will be no indirect call to Foo's destructor.

是的,如果一个对象超出范围,就会调用析构函数。但是不,在这种情况下不会调用析构函数,因为在作用域中只有一个指针,这个指针没有特定的析构函数,所以不会间接调用Foo's析构函数。

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 have a 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的析构函数会删除bar,但是bar从来没有被初始化,也没有被分配到指向一个实际对象的地址,所以delete调用会给出未定义的行为,可能会导致崩溃。

#3


2  

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)

从技术上讲,由于您在主服务器中,所以它不是一个内存泄漏,因为当应用程序没有终止时,您可以访问每个已分配的变量。在这方面,我引用了亚历山大(来自现代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,因为这是一种极其糟糕(而且危险)的实践。

#4


1  

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用动态存储而不是自动存储分配对象,它在函数的末尾不会超出范围。因此它也不会被删除,而且你已经泄露了内存。

#5


-5  

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.

在此实例中,当主返回时它是程序的结束,操作系统将处理释放所有资源。例如,如果这是任何其他函数,则必须使用delete。