2016-04-15 135 views
7

我想知道什么时候应该在C++的堆栈上分配一个类?我在Java中拥有强大的背景,在Java中,所有类都使用关键字new在堆上分配。在C++中,我可以在堆栈和堆分配之间选择,但现在已经引入了智能指针,分配所有不会将所有权转让给std::unique_ptr的所有权更有意义。C++堆栈与堆分配

我真的不能想到任何情况下,哪里有必要或更好地使用堆栈分配。也许在嵌入式系统中进行某种优化?

+2

只是一个简单的'std :: unique_ptr'是一个“堆栈”的对象。顺便说一句,我们称之为自动和动态对象,因为C++没有堆栈或堆的概念。恕我直言,你想尽可能使用自动对象, – NathanOliver

+9

你通常使用相反的原则:如果动态分配是不必要的,你不这样做。默认情况下的动态分配是“过早悲观”。 – molbdnilo

回答

14

使用自动(堆)分配每当功能范围 - 或一个控制块的诸如forwhileif在函数内部等的范围 - 是用于寿命对象需要的良好匹配。这样,如果对象拥有/控制任何资源(如动态分配的内存,文件句柄等) - 它们将在析构函数调用期间被释放,因为该范围被留下。 (当垃圾收集器停工时,不会在某些不可预测的情况下发生)。

只使用new,如果有一个明确的需求,如:

  • 需要的对象的生活比功能范围较长,

  • 所有权移交给一些其他的代码

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

  • 一个特别大的分配,将吃起来多的堆栈(你的OS /过程将有“协商”的限制,通常在1-8 +兆字节范围)

    • 如果这是唯一的因为您使用的是动态分配,并且您希望对象的生命周期与函数中的作用域绑定,所以您应该使用本地std::unique_ptr<>来管理动态内存,并确保无论您如何离开作用域,它都会被释放:通过return,throw,break等。(您也可以使用std::unique_ptr<>中的数据成员class/struct来管理对象拥有的任何内存。)

马修范NEVEL评论低于约C++ 11移动语义 - 的相关性的是,如果具有控制大量的动态分配(堆)存储器,移动该堆栈上的小管理对象语义学授予额外的保证和对管理对象何时将其资源移交给其他代码拥有的另一个管理对象(通常是调用者,但可能是某些其他容器/对象的注册表)的细粒度控制。这种切换可以避免即时复制/复制堆上的数据。此外,elision返回值优化经常允许名义上自动/堆栈托管的变量直接在某些内存中构建,它们最终将被分配/返回,而不是在稍后复制。

+0

这是一个很好的总结。我最近重新编写了一些将大量对象放入堆栈的代码。如果你不小心,你可以在一个更大的程序中用完堆栈空间,或者使用深度递归。 –

+0

有关C++ 11移动语义的一些细节,答案将是完美的我认为:upvote –

+0

好的总结,如果你添加什么时候应该使用std :: unique_ptr而不是堆栈分配,我会给你答案打勾。 – KillerZefi

1

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