何时以及为什么在堆C++上声明成员变量

When and why to declare member variables on the heap C++

本文关键字:声明 成员 变量 C++ 为什么 何时      更新时间:2023-10-16

好吧,所以我对C++编程很陌生,几天来我一直在四处寻找这个问题的决定性答案。什么时候应该在堆上声明成员变量,而不是在堆栈上声明?我发现的大多数答案都涉及其他问题,但我想知道什么时候最好对成员变量使用堆,以及为什么最好对成员进行堆而不是堆叠。

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

  1. 人们应该避免用"堆"answers"堆栈"来思考。这些是编译器/平台的实现细节,而不是语言的细节1相反,从对象寿命的角度思考:对象的寿命应该与其"父对象"的寿命相对应,还是应该比它更长寿?如果需要后者,则需要使用new(直接或间接)来动态分配对象。

  2. 成员变量始终与其父级具有相同的生存期。成员变量可以是一个指针,它所指向的对象很可能具有独立的生存期。但是指向的对象不是成员变量。

然而,你的问题没有一个普遍的答案。严格地说,除非有充分的理由,否则不要动态分配。正如我上面暗示的,这些原因通常对应于生命周期需要与其"父"不同的情况。


1.事实上,C++标准并没有真正谈论"堆"answers"堆栈"。在优化或总体考虑性能时,它们很重要,但从程序功能的角度来看,它们大多无关紧要

成员变量是类本身的成员。它们都没有打开堆也不在堆栈上,或者更确切地说,它们是类所在的位置

添加间接级别和分配堆上单独的成员:多态性(如果成员的类型不总是一样)是迄今为止最常见的。

为了弄清楚一些术语:您所称的heapstack描述对象的生存期。第一个表示生存期为dynamic,第二个为automatic,第三个(您没有提及)为static

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

一个需要动态生命周期的成语就是皮条成语。

大多数通用编程库都更侧重于值和值语义,因此您不会太多地使用动态绑定,自动生存期也变得更加常见。

还有一些例子表明,由于更具体的实施原因,需要动态分配:

  • 动态调整对象(容器)大小
  • 处理不完全类型(参见皮条客习语)
  • 类型的易为空性

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

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

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

考虑这个例子:

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

例如,如果你的列表中有100个节点,那么你的头部成员将是巨大的。因为它将下一个节点容纳在自己内部,所以它需要有足够的大小来容纳它,下一个容纳下一个,依此类推。所以头部必须有足够的空间来容纳99个节点,然后98个,依此依此类推…

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