何时应该在堆栈而不是堆上分配类

时间:2012-09-08 17:44:43

标签: c++

过去每当我需要创建一个类的实例时,我都会使用new在堆上分配它(除了stl类和数学类,如vec3和mat4)。

然而,我只是批评我的一些代码,并意识到技术上我可以只是在堆栈上制作这些类。它们不是很大,不需要在当前范围之外进行修改等。当我(偶尔)需要将它们传递给另一个函数时,我可以像使用指针一样轻松地使用引用。

过去我总是默认在堆上分配,并且在某些情况下只使用堆栈,但是现在我想知道默认情况下在堆栈上分配是否更好,并且只在使用堆时才使用堆

  • 确实需要一个指针(即对象的生命周期超出声明范围)
  • 类或数组对于堆栈来说太大了
  • 继承需要它(抽象基类/接口)
  • 别的什么?

这也提出了一个问题:一个类有多大(大致)在堆栈上合理分配? (假设我们正在努力,至少是智能手机,并进入高端桌面)我只是担心不必要的堆栈大小限制? (可能,只要我们不讨论大型数组,并且没有类甚至接近千字节)

4 个答案:

答案 0 :(得分:7)

您的默认行为应为:

如果物体的寿命与特定范围一致 即在编译时很容易确定

  

然后它应该是一个自动存储持续时间对象(像堆栈一样)

如果对象的生命周期在运行时定义并超出当前范围

  

然后它应该是一个动态存储持续时间对象(像堆一样)

注意:所有动态存储持续时间对象都应通过将它们包装在适当的RAII类中来控制其生命周期。通常这意味着:对于单个对象,智能指针,而多个对象最终在容器中。

讨厌看东西定义为堆栈Vs堆。因为它没有传达情况的真实语义。

 int x;       // its on the stack
 struct X
 {
     int x;   // Is this a stack or heap object?
 }            // It depends on its parent.


 // But in both cases it is an automatic storage duration object.
 // In both cases the lifespan's are well defined.
 //     The first is defined by the scope it is declared within.
 //     The second is defined by the lifespan of its parent.

您应该考虑自动/动态“存储持续时间”对象。这传达了语言的正确语义。

注意有两种其他类型的变量,因此产生四种不同类型的变量。自动/动态/静态/线程'存储持续时间'对象。

答案 1 :(得分:4)

我更喜欢在堆栈上分配,原因有两个。首先,在其他条件相同的情况下,它比堆快。此外,解除分配是自动发生的,我不需要记住delete它(当然,还有auto_ptr等等,以帮助解决这个问题。

  

确实需要一个指针

可以将指针传递给堆栈上的对象。只需确保该指针的用户在其生命周期到期后不会访问该对象。

  

类或数组对于堆栈来说太大了

只有真正重要的事情应该重要。你可能有1MB的堆栈,所以在出现问题之前你可以放置大约1000个1KB的对象。

  

继承需要它

为什么会这样?

  

其他什么?

对象所需的生命周期长于堆栈帧的生命周期。这是在堆上分配的主要原因。

答案 2 :(得分:1)

  

什么时候应该在堆栈而不是堆上分配一个类?

尽可能不会给您带来很大的不便。会有例外,但作为一般规则回答您的问题:创建实例时,new / new[]键入不到百分之一的时间。< / p>


  

确实需要一个指针(即对象的生命周期超出声明范围)

是的,在适当的情况下。从你对OP中描述的堆的使用来判断,这可能比你想象的要少得多。

  

类或数组对于堆栈来说太大了

是的,这不应该是一个值得关注的问题 - 大型通常的类表明您的课程出现了根本性问题。客户友好类可能会考虑在堆上创建那些巨大的,固定大小的数组。

  

继承需要它(抽象基类/接口)

在某些情况下(例如,存在抽象工厂或存在多态类型的深层克隆),但是 factory 会创建类型,并且问题通常会从您的程序中移开在你考虑它之前使用堆栈。

  

其他什么?

没有


原因:

  • 它清晰,简洁,其寿命和范围都很明确。
  • 减少资源消耗。
  • 与内存相关的错误或可能出错的错误。
  • 速度。堆栈分配非常快。更少的锁。

答案 3 :(得分:-2)

仅在需要动态分配内存时才在堆上进行分配。这意味着您不知道在编译时需要分配多少。 你所有其他时间在堆栈上分配