从Stroustrup的Foundations of C++开始,他提供了一种纯粹的面向对象语言(第4页)。
class complex { double re, im; /* … */ };
complex a[ ] = { {1,2}, {3,4} };
他认为纯粹的面向对象语言中的a
是在堆上分配的,而a
的内存布局如下所示:
可能的大小是 3 * sizeof(参考)+ 3 * sizeof(heap_overhead)+ 4 * sizeof(double)。假设引用是一个单词而堆开销是两个单词,我们得到的可能大小为19个单词,与C ++的8个单词进行比较。这种内存开销伴随着分配和间接访问元素的运行时开销。间接访问内存通常会导致缓存利用率出现问题并限制可ROM性。
我注意到最高参考没有堆开销(白色矩形)。
我想这是一种普遍的现象,而不是纯粹的OO示例语言。
但是我找不到任何参考(我承认这不是一个搜索引擎友好的问题)。
感谢您的回答。但是,我忘记发布我的原始猜测。 (道歉,这是我的错。)
实际上,我也认为因为a
本身可能在堆栈或其他地方分配,所以它本身不会有堆开销。但后来,我注意到BS也说:
第4页将此与“纯面向对象语言”中更典型的布局进行比较,其中
each user-defined object is allocated separately on the heap
并通过引用进行访问...
。
所以,我认为他已经将实现限制为仅限堆(或无堆栈)。
(当然,也许我正在读这句话太多了。)
答案 0 :(得分:3)
顶层参考生活在任何地方。以下是一些选项:
a
可以表示为。a
也可以表示为,在这种情况下,它既没有堆开销也没有内存开销:相反,它只是"只有"需要使用注册表。在此上下文中的主要实现是这些引用不是实际对象,即,您不能引用引用。结果,不需要保持参考的位置固定。它们可以(并且它们实际上代表它们时)实际值。典型实现中的引用值是对象的地址。
其他实体是对象:
complex
用于创建一个实际嵌入奇数double
"对象"这也是价值而不是实际的对象。a
是此模型中引用两个complex
对象的数组对象。答案 1 :(得分:2)
当您在堆上存储时,会出现堆开销。这两个complex
值存储在堆上,因此它们会产生开销。引用数组也存储在堆上,因此会产生开销。
但是,对数组的引用是 not 存储在堆上。通常,此引用将作为本地变量放在堆栈上,或者可以通过使用CPU寄存器来优化堆栈存储。在任何一种情况下,引用本身只是一个本地指针变量,它本身没有堆分配开销。
答案 2 :(得分:1)
这里的想法是顶层引用要么是堆栈上的本地/参数/寄存器中(没有堆开销),要么是更大结构的一部分(反过来可能在堆上分配) ,但我们不计算它的开销,因为它不是特定于这个特定的引用,而是在其他数据成员之间共享。)
实际上,我也认为因为
a
本身可能会在堆栈上分配 或者其他任何东西,所以它本身不会有堆开销。但后来我注意到了 BS还说:第4页中的将此与“纯面向对象语言”中更典型的布局进行比较,其中
each user-defined object is allocated separately on the heap
并通过引用进行访问...。
所以,我认为他已经将实现限制为仅限堆(或者 堆栈更小)。
(当然,也许我对这句话读得太多了)
我认为你正在阅读太多内容。 Stroustroup所指的现实世界语言(例如Python,Java或C# - 如果我们将自己局限于盒装类型)确实有一个包含普通引用数组的“常规”堆栈。
答案 3 :(得分:1)
complex a[ ] = { {1,2}, {3,4} };
让我们打破这种 - 自下而上的方法。
complex
个对象:Complex{1,2}
和Complex{3,4}
。复杂{double,double}
每个complex
对象都有double
值的堆地址(白色)和占用的空间(蓝色)。
{
大括号,列表初始化 array
个Complex
个对象。array {Complex1,Complex2}
它具有array
对象(白色)的地址,以及两个Complex
对象的两个引用(蓝色)。
complex a
没有任何开销,因为这只是一个存在于堆栈中的局部变量。