C ++堆栈与堆分配

时间:2016-04-15 11:56:14

标签: c++ memory-management

我想知道何时应该在C ++中为堆栈分配一个类?我有很强的Java背景和Java,所有类都是使用new关键字在堆上分配的。在C ++中,我可以在堆栈和堆分配之间进行选择,但是现在引入了智能指针,分配所有不会使用std::unique_ptr转移所有权的内容更有意义。

我无法想到任何使用堆栈分配的必要或更好的情况。也许在嵌入式系统中进行某种优化?

2 个答案:

答案 0 :(得分:16)

只要函数范围 - 或函数内的forwhileif等控制块的范围 - 是好的,就使用自动(堆栈)分配匹配对象所需的生命周期。这样,如果对象拥有/控制任何资源,例如动态分配的内存,文件句柄等等 - 它们将在析构函数调用期间被释放,因为该范围被保留。 (当垃圾收集器结束时,不会出现一些无法预测的情况。)

如果有明确需要,请仅使用new,例如:

  • 要求对象的寿命超过函数范围

  • 将所有权移交给其他代码

  • 有一个指向基类的指针容器,然后可以多态处理(即使用虚拟调度到派生类函数实现),或者

  • 一个特别大的分配,会耗尽大部分堆栈(您的操作系统/进程将“协商”一个限制,通常在1-8 +兆字节范围内)

    • 如果这是您使用动态分配的唯一原因,并且您确实希望对象的生命周期与函数中的作用域相关联,则应使用本地std::unique_ptr<>来管理动态内存,以及无论您如何离开范围,都要确保它已发布:returnthrowbreak等。(您也可以在{{{{}}中使用std::unique_ptr<>数据成员1}} / class来管理对象拥有的任何内存。)
Mathieu Van Nevel在下面评论了C ++ 11移动语义 - 相关性是,如果堆栈上有一个控制大量动态分配(堆)内存的小型管理对象,移动语义可以提供额外的保证和罚款 - 对管理对象何时将其资源移交给其他代码所拥有的另一个管理对象(通常是调用者,但可能是其他一些容器/对象注册表)的控制。这种切换可以避免即使在瞬间复制/复制堆上的数据。此外, elision return-value-optimization 通常允许名义上自动/堆栈托管的变量直接构建在最终被分配/返回的某些内存中,而不是在以后复制。

答案 1 :(得分:1)

在大型代码库中,我们对简单的struct对象使用堆栈分配,而对于更复杂的类(涉及多态,内存所有权等),我们总是使用动态分配。