【问题标题】:C++ stack vs heap allocationC++ 堆栈与堆分配
【发布时间】:2016-04-15 11:56:14
【问题描述】:

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

我真的想不出在哪些情况下有必要或更好地使用堆栈分配。也许是为了在嵌入式系统中进行某种优化?

【问题讨论】:

  • 仅供参考,std::unique_ptr 是一个基于“堆栈”的对象。顺便说一句,我们称之为自动和动态对象,因为 C++ 没有堆栈或堆的概念。恕我直言,您希望尽可能使用自动对象,
  • 您通常使用相反的原则:如果不需要动态分配,您就不要这样做。动态分配默认为“过早悲观化”。

标签: c++ memory-management


【解决方案1】:

只要函数范围(或函数内部的forwhileif 等控制块的范围)与对象的生命周期相匹配,就使用自动(堆栈)分配需要。这样,如果对象拥有/控制任何资源,例如动态分配的内存、文件句柄等 - 它们将在析构函数调用期间被释放,因为该范围已离开。 (不会在垃圾收集器结束时的某个不可预测的时间)。

仅在有明确需要时才使用new,例如:

  • 需要对象的寿命比函数范围长,

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

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

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

    • 如果这是您使用动态分配的唯一原因,并且您确实希望对象的生命周期与函数中的范围相关联,则应使用本地 std::unique_ptr<> 来管理动态内存,并确保它无论您如何离开范围都会释放:returnthrowbreak 等。(您也可以在 class/struct 中使用 std::unique_ptr<> 数据成员来管理任何内存对象拥有。)

Mathieu Van Nevel 在下面讨论 C++11 移动语义 - 相关性是,如果您在堆栈上有一个控制大量动态分配(堆)内存的小型管理对象,移动语义会给予额外的保证和罚款- 管理对象何时将其资源移交给其他代码拥有的另一个管理对象(通常是调用者,但可能是一些其他容器/对象寄存器)的粒度控制。这种切换可以避免堆上的数据被复制/复制,即使是暂时的。此外,elisionreturn-value-optimisation 通常允许名义上自动/堆栈托管的变量直接在它们最终被分配/返回的内存中构造,而不是以后复制到那里。

【讨论】:

  • 这是一个很好的总结。我最近重新编写了一些代码,将一组非常大的对象放入堆栈。如果您不小心,可能会在较大的程序或深度递归的程序中耗尽堆栈空间。
  • 关于 c++11 移动语义的一些细节,我认为答案将是完美的:upvote
  • 好总结,如果你补充一下我什么时候应该使用 std::unique_ptr 而不是堆栈分配,我会给你答案。
  • 不想听起来粗鲁,我就是这样。
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 2011-10-06
    • 2011-05-28
    • 1970-01-01
    • 2011-09-06
    • 2013-10-20
    • 2012-01-18
    • 2012-12-23
    • 1970-01-01
    相关资源
    最近更新 更多