为什么基本引用没有堆开销?

时间:2018-05-24 05:34:06

标签: c++ memory reference operating-system heap

StroustrupFoundations of C++开始,他提供了一种纯粹的面向对象语言(第4页)。

class complex { double re, im; /* … */ };
complex a[ ] = { {1,2}, {3,4} };

他认为纯粹的面向对象语言中的a是在上分配的,而a的内存布局如下所示: enter image description here

  

可能的大小是 3 * sizeof(参考)+ 3 * sizeof(heap_overhead)+ 4 * sizeof(double)。假设引用是一个单词而堆开销是两个单词,我们得到的可能大小为19个单词,与C ++的8个单词进行比较。这种内存开销伴随着分配和间接访问元素的运行时开销。间接访问内存通常会导致缓存利用率出现问题并限制可ROM性。

我注意到最高参考没有堆开销(白色矩形)。

我想这是一种普遍的现象,而不是纯粹的OO示例语言。

但是我找不到任何参考(我承认这不是一个搜索引擎友好的问题)。

更新

感谢您的回答。但是,我忘记发布我的原始猜测。 (道歉,这是我的错。

实际上,我也认为因为a本身可能在堆栈或其他地方分配,所以它本身不会有堆开销。但后来,我注意到BS也说:

  

将此与“纯面向对象语言”中更典型的布局进行比较,其中 each user-defined object is allocated separately on the heap 并通过引用进行访问...

第4页

所以,我认为他已经将实现限制为仅限堆(或无堆栈)。

(当然,也许我正在读这句话太多了。)

4 个答案:

答案 0 :(得分:3)

顶层参考生活在任何地方。以下是一些选项:

  1. 它可以存在于堆栈中。代码中的a可以表示为。
  2. 它嵌入到现有对象中。
  3. 分配内存只是保持句柄。在这种情况下,它会产生内存开销。
  4. 它是一个全球性的实体。
  5. 引用可以存在于寄存器中。代码中的a也可以表示为,在这种情况下,它既没有堆开销也没有内存开销:相反,它只是"只有"需要使用注册表。
  6. 在此上下文中的主要实现是这些引用不是实际对象,即,您不能引用引用。结果,不需要保持参考的位置固定。它们可以(并且它们实际上代表它们时)实际值。典型实现中的引用值是对象的地址。

    其他实体是对象:

    • complex用于创建一个实际嵌入奇数double"对象"这也是价值而不是实际的对象。
    • a是此模型中引用两个complex对象的数组对象。

答案 1 :(得分:2)

当您在堆上存储时,会出现堆开销。这两个complex值存储在堆上,因此它们会产生开销。引用数组也存储在堆上,因此会产生开销。

但是,对数组的引用是 not 存储在堆上。通常,此引用将作为本地变量放在堆栈上,或者可以通过使用CPU寄存器来优化堆栈存储。在任何一种情况下,引用本身只是一个本地指针变量,它本身没有堆分配开销。

答案 2 :(得分:1)

这里的想法是顶层引用要么是堆栈上的本地/参数/寄存器中(没有堆开销),要么是更大结构的一部分(反过来可能在堆上分配) ,但我们不计算它的开销,因为它不是特定于这个特定的引用,而是在其他数据成员之间共享。)

  

实际上,我也认为因为a本身可能会在堆栈上分配   或者其他任何东西,所以它本身不会有堆开销。但后来我注意到了   BS还说:

     
    

将此与“纯面向对象语言”中更典型的布局进行比较,其中 each user-defined object is allocated separately on the heap 并通过引用进行访问...

  
     第4页中的

     

所以,我认为他已经将实现限制为仅限堆(或者   堆栈更小)。

     

(当然,也许我对这句话读得太多了)

我认为你正在阅读太多内容。 Stroustroup所指的现实世界语言(例如Python,Java或C# - 如果我们将自己局限于盒装类型)确实有一个包含普通引用数组的“常规”堆栈。

答案 3 :(得分:1)

complex a[ ] = { {1,2}, {3,4} };

让我们打破这种 - 自下而上的方法。

  1. 您有两个列表已初始化的complex个对象Complex{1,2}Complex{3,4}
  2.   

    复杂{double,double}

    每个complex对象都有double值的堆地址(白色)和占用的空间(蓝色)。

    1. 接下来是外部{大括号,列表初始化 arrayComplex个对象。
    2.   

      array {Complex1,Complex2}

      它具有array对象(白色)的地址,以及两个Complex对象的两个引用(蓝色)。

      1. 最后,complex a没有任何开销,因为这只是一个存在于堆栈中的局部变量。