类私有数据 - 在堆栈或堆上

Posted

技术标签:

【中文标题】类私有数据 - 在堆栈或堆上【英文标题】:Class private data - on stack or heap 【发布时间】:2012-11-17 00:44:31 【问题描述】:

在以下代码中:

class Array 
   public:
      int& operator[] (unsigned i)  if (i > 99) error(); return data[i]; 
   private:
      int data[100];
;

int main()

   Array a;
   a[10] = 42;
   a[12] += a[13];
   ...

(如果我错了,请纠正我)类型为 Array 的变量 a 在堆栈上,因为没有使用 new 来分配它。 Array类有int data[100],操作符重载返回对data中特定索引的引用。

参考question。

我的问题是 int data[100] 是在堆栈上还是在堆上?我认为它不应该是堆栈,否则像上面的引用返回如何仍然有效。

谢谢。

【问题讨论】:

【参考方案1】:

它在堆栈上,因为您已经注意到 a 是在堆栈上分配的。

栈和堆一样是内存;您可以返回对其中一部分的引用,就像在堆上分配的内存一样。唯一的区别在于内存的管理方式。

您唯一需要注意的是不要访问已被释放的内存;在堆栈的情况下,这发生在a 范围的末尾,而堆分配的数据必须被显式删除。

在您提到的问题中,对堆栈上声明的变量的引用是从函数返回的;在这种情况下,该变量在函数退出时被销毁,这就是该代码错误的原因。但是,在您的情况下,您将返回对 data 的一部分的引用,其生命周期与 Array 对象的生命周期匹配;所以只要a没有被破坏,以这种方式访问​​它的数据是安全的。

【讨论】:

【参考方案2】:

正如您所说,“数组类型的变量 a 在堆栈上”。从技术上讲,名为a对象 在堆栈上。这意味着对象a的所有成员变量都在堆栈上。

这意味着返回对名为data 的成员数组中的元素的引用是非常危险的。编译器会允许这样做,但是如果您在变量 a 超出范围时尝试访问此引用,那么您将遇到未定义的行为。

在您的示例中,对operator[]() 的所有调用都在同一个方法中,所以一切都很好。

【讨论】:

从技术上讲,名为 a 的对象分配有自动存储持续时间。该语言不需要堆栈结构来实现这种存储。只是“技术”:D @EdS。感谢您的澄清;-)【参考方案3】:

它在堆栈上。为什么参考返回是一个问题?您可以毫无问题地创建和使用对堆栈中事物的引用。

void foo(void)

 int i;
 int& j = i; // reference to variable on the stack
 j = 2;

您认为这里可能存在什么问题?

【讨论】:

关注的是悬空引用【参考方案4】:

我的问题是 int data[100] 是在堆栈上还是在堆上?我认为它不应该是堆栈,否则像上面的引用返回如何仍然有效。

它是按自动存储持续时间分配的,即堆栈,而不是堆。您没有动态分配任何东西,因此不会发生动态(堆)分配。这将是一件可怕的事情,而 C++ 就是不为你不使用的东西付费。

如果data 已离开其声明范围,即Array 实例的范围,则对data 元素或data 本身的引用将无效。现在,Array 类型是否应该使用动态分配?几乎可以肯定,是的,对于通用容器。您有责任确保不保留对错误数据的引用或指针。

【讨论】:

【参考方案5】:

它将在堆栈上。如果您在“a”超出范围后尝试使用该引用,您将获得未定义的行为。希望它会很快崩溃。

【讨论】:

以上是关于类私有数据 - 在堆栈或堆上的主要内容,如果未能解决你的问题,请参考以下文章

如何确定 Rust 中的 new() 何时在堆栈或堆上分配

是否在C中的堆栈或堆上创建激活记录?

c#结构/类堆栈/堆控制?

对象的私有成员是在堆上还是在栈上?

C++ 类可以确定它是在堆栈上还是在堆上?

堆和堆栈内存是如何管理、实现和分配的?