本篇讲解的问题如下:对象在内存中到底是如何安家的?它们何时生,何时死?

Stack内存的特性

对象的第一个家是栈。栈是存在于某一作用域内的一块内存空间。当调用一个函数时,函数本身就会形成一个栈,用于存放参数、返回地址以及局部对象。当程序执行流离开该作用域,在此作用域内创建的所有非静态的局部对象都会被自动销毁。

image

生命周期路径如下:

image

常见误解:认为栈上对象”自动销毁”意味着不需要写析构函数。实际上,如果对象内部管理了堆内存(如自实现字符串中的 char* 成员),其析构函数中必须手动释放堆内存,否则仍然会造成内存泄漏。栈的”自动”只保证栈内存被回收,但不保证内部堆内存被释放。

Heap内存的特性

对象的第二个家是堆。堆内存的生命周期不受作用域限制,由程序员通过 newdelete 手动控制。这使得堆上对象的生命周期可以超越创建它的函数,但也带来了忘记释放导致内存泄漏的风险。

于是栈和堆的区别如下:
image

关键语义:new 在堆上分配内存并调用构造函数。delete 先调用析构函数再释放内存。如果只 newdelete,堆内存永远不会被自动回收,直到程序结束。

易错点:忘记调用 delete 导致内存泄漏。更隐蔽的错误是:在异常路径中跳过了 delete,或者对同一块内存调用了两次 delete(导致未定义行为)。建议使用智能指针(如 std::unique_ptr)来自动管理堆对象的生命周期。

全局与静态对象的生命周期

除了栈和堆,C++ 中还有全局对象和静态对象。它们的生命周期贯穿整个程序运行期:在 main() 函数执行之前就被构造,在 main() 结束之后才被析构。