在以下代码中:
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数据[100],运算符重载返回对数据中特定索引的引用。
参考question。
我的问题是int数据[100]是在堆栈还是堆上?我认为它不应该是堆栈,否则如上所述的引用返回仍然可以工作。
感谢。
答案 0 :(得分:2)
它在堆栈上,因为你已经注意到a
被分配在堆栈上。
堆栈就像堆一样是内存;你可以返回对它的一部分的引用,就像在堆上分配的内存一样。唯一的区别在于如何管理内存。
唯一需要注意的是不要访问已经解除分配的内存;在堆栈的情况下,这发生在a
范围的末尾,而必须明确删除堆分配的数据。
在您提到的问题中,从函数返回对堆栈上声明的变量的引用;在这种情况下,当函数退出时,变量将被销毁,这就是代码错误的原因。但是,在您的情况下,您将返回对data
部分Array
的引用,该部分的生命周期与a
对象的生命周期匹配;所以只要{{1}}没有被销毁,以这种方式访问它的数据就是安全的。
答案 1 :(得分:0)
它在堆栈上。为什么引用返回是一个问题?您可以毫无问题地创建和使用对堆栈中的内容的引用。
void foo(void)
{
int i;
int& j = i; // reference to variable on the stack
j = 2;
}
您认为这里有什么问题?
答案 2 :(得分:0)
它将在堆栈中。如果在“a”超出范围后尝试使用该引用,则会得到未定义的行为。希望它很快就会崩溃。
答案 3 :(得分:0)
我的问题是int数据[100]是在堆栈还是堆上?我认为它不应该是堆栈,否则如上所述的引用返回仍然可以工作。
它被分配了自动存储持续时间,即堆栈,而不是堆。您尚未动态分配任何内容,因此不会发生动态(堆)分配。这将是一个可怕的事情,C ++就是不为你不使用的东西买单。
如果data
已离开其声明范围,即data
实例的范围,则对data
或Array
本身的元素的引用将无效。现在,Array
类型应该使用动态分配吗?对于通用容器,几乎可以肯定,是的。您有责任确保不保留对不良数据的引用或指示。
答案 4 :(得分:0)
正如你所说,“Array类型的变量a在堆栈中”。从技术上讲,名为a
的对象位于堆栈中。这意味着对象a
的所有成员变量都在堆栈中。
这意味着返回对名为data
的成员数组中元素的引用是非常危险的。编译器将允许它,但如果在变量a
超出范围时尝试访问此引用,则会遇到未定义的行为。
对于您的示例,对operator[]()
的所有调用都在同一方法中,因此一切正常。