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