3

在以下代码中:

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],运算符重载返回对数据中特定索引的引用。

参考问题

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

谢谢。

4

5 回答 5

3

它在堆栈上,因为正如您所指出的,它是在堆栈上a分配的。

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

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

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

于 2012-11-29T01:32:17.053 回答
1

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

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

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

于 2012-11-29T01:32:53.653 回答
0

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

void foo(void)
{
 int i;
 int& j = i; // reference to variable on the stack
 j = 2;
}

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

于 2012-11-29T01:32:17.477 回答
0

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

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

如果离开datadatadata的声明范围,即Array. 现在,Array类型应该使用动态分配吗?几乎可以肯定,是的,对于通用容器。您有责任确保您没有保留对错误数据的引用或指针。

于 2012-11-29T01:32:45.320 回答
-1

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

于 2012-11-29T01:32:37.110 回答