构造函数和析构函数如何工作?

How the constructor and destructor work?

class Foo{
public:
    Foo(){
        cout <<"C ";
    }
    ~Foo(){
        cout <<"D ";
    }
};

void func(){
    Foo* p = new Foo;
    p = NULL;
}

int main(){
    Foo a;
    for (int i=0; i<1; i++){
        Foo b;
        if (true){
            Foo c;
        }
        func();
    }
    return 0;
}

这道题的输出是C C C D C D D,如果我把main函数中的func()去掉,输出就变成了C C C D D D,前3个C我看懂了,但是我不明白后面的剩下的请解释一下,谢谢

  1. C-a构造
  2. C-b构造
  3. C - c构造
  4. D - c 被破坏因为你离开了作用域
  5. C - 一个对象 Foo 被动态分配并由 p 指向,但由于它是动态分配的,并且从未被删除,因此它永远不会被破坏。
  6. D - b 被破坏
  7. D - a 被破坏

C C C D C D D 的顺序是:

  1. C - 构造 A
  2. C - 构造 B
  3. C - 构造 C
  4. D - 破坏 C
  5. C - 构造 p(在 func 中)
  6. D - 摧毁 B
  7. D - 摧毁 A

// p 的内存泄漏(在 func 中)

包含func();调用时,采取的步骤是:

Foo a; -> C

Foo b; -> C

Foo c; -> C

Left the scope of Foo c -> D

func(); call ->
    new Foo; -> C

Finished func() call, left the scope of Foo b -> D

Left the scope of Foo a -> D

请注意,在 func() 中创建的 Foo 对象永远不会被解构,这意味着您有内存泄漏。

对象的作用域a是main函数外层代码块的作用域。它是创建的第一个对象和删除的最后一个对象。

int main(){
    Foo a;
    // ...
    return 0;
}

C C C D C D D
|           |
a           a

然后在只有一次迭代的 for 循环中创建对象 b,在循环的第一次迭代后删除

for (int i=0; i<1; i++){
    Foo b;
    // ...
}

C C C D C D D
| |       | |
a b       b a

然后在语句块范围内if

    if (true){
        Foo c;
    }

创建和删除对象c

C C C D C D D
| | | |   | |
a b c c   b a

之后函数func被调用

func();

在函数内部,使用 operator new 创建了一个未命名的对象,并由指针 p.

指向
void func(){
    Foo* p = new Foo;
    p = NULL;
}

C C C D C D D
| | | | | | |
a b c c p b a

这个对象没有被删除,因为没有为这个对象调用删除运算符。所以存在内存泄漏。

就是这样。