类私有数据 - 在堆栈或堆上
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”超出范围后尝试使用该引用,您将获得未定义的行为。希望它会很快崩溃。
【讨论】:
以上是关于类私有数据 - 在堆栈或堆上的主要内容,如果未能解决你的问题,请参考以下文章