18

好的,所以我是 C++ 编程的新手,我已经四处寻找了几天的决定性答案。我应该什么时候在堆和堆栈上声明成员变量?我发现的大多数答案都涉及其他问题,但我想知道何时最好将堆用于成员变量,以及为什么堆成员而不是堆叠成员更好。

4

5 回答 5

23

首先要掌握两个重要概念:

  1. 应该避免考虑“堆”和“堆栈”。这些是您的编译器/平台的实现细节,而不是语言的实现细节。1 相反,从对象生命周期的角度来考虑:对象的生命周期应该与其“父”的生命周期相对应,还是应该比它更长?如果您需要后者,那么您需要使用new(直接或间接)动态分配对象。

  2. 成员变量的生命周期总是与其父变量相同。成员变量可能是一个指针,它指向的对象很可能有一个独立的生命周期。但是指向的对象不是成员变量。

但是,您的问题没有一般性的答案。粗略地说,除非有充分的理由,否则不要动态分配。正如我上面所暗示的,这些原因通常对应于生命周期需要与其“父级”不同的情况。


1.确实,C++标准并没有真正谈论“堆”和“堆栈”。在优化或一般考虑性能时,它们很重要,但从程序功能的角度来看,它们大多无关紧要。

于 2012-07-13T20:04:03.907 回答
5

成员变量是类本身的成员。它们既不在堆上也不在堆栈上,或者更确切地说,它们在类本身所在的地方。

添加间接级别并在堆上单独分配成员的原因很少:多态性(如果成员的类型并不总是相同)是迄今为止最常见的。

于 2012-07-13T20:10:05.330 回答
2

直截了当地了解一些术语:你称之为 aheapstack描述对象的生命周期。第一个意味着生命周期是dynamic,第二个automatic和第三个(你没有提到)是static

通常你需要dynamic一个对象的生命周期,当它应该超过它被创建的范围时。另一个常见的情况是你希望它在不同的父对象之间共享。此外,当您使用高度面向对象的设计(使用大量多态性,不使用值)时,动态生命周期也是必要的,例如Qt.

需要动态生命周期的成语是 pimpl-idiom。

大多数通用编程库更侧重于值和值语义,因此您不会过多地使用动态绑定,并且自动生命周期变得更加普遍。

还有一些示例,出于更多实现特定的原因需要动态分配:

  • 动态大小的对象(容器)
  • 处理不完整的类型(参见 pimpl-idiom)
  • 类型的简单可空性

所有这些都只是一般指导方针,必须根据具体情况决定。一般来说,比起动态对象,更喜欢自动对象。

于 2012-07-13T20:10:55.577 回答
1

堆栈指的是call stack. 函数调用、返回地址、参数和局部变量都保存在调用堆栈中。每当您传递参数或创建局部变量时,都会使用堆栈内存。堆栈只有临时存储。一旦当前函数超出范围,您就无法再访问任何参数变量。

是用于动态分配的大型内存池。当您使用new运算符分配内存时,此内存是从堆中分配的。当您创建不想在当前函数终止(失去作用域)后丢失的对象时,您希望分配堆内存。对象存储在堆中,直到使用delete或释放空间free()

于 2012-07-13T20:08:31.843 回答
0

考虑这个例子:

你实现了一个链表,它有一个类节点的字段成员头。
每个节点都有一个字段成员next。如果此成员属于 Node 类型而不是 Node*,则每个 Node 的大小将取决于链中它之后的节点数量。

例如,如果您的列表中有 100 个节点,那么您的头成员将是巨大的。因为它在自身内部保存下一个节点,所以它需要有足够的大小来保存它,并且 next 保存下一个,依此类推。所以头部必须有足够的空间来容纳 99 个节点和下一个 98 等等......

你想避免这种情况,所以在这种情况下,最好在每个节点中都有指向下一个节点的指针,而不是下一个节点本身.

于 2017-04-07T06:16:27.213 回答