【问题标题】:Derived class is bigger than base class even though it consists of reference variables派生类比基类大,即使它包含引用变量
【发布时间】:2013-04-10 07:54:45
【问题描述】:

从我目前阅读的内容来看,似乎引用变量根本不应该占用任何内存。相反,它们被视为它们引用的完全相同的变量,但名称不同。

但是,当我运行以下代码时,似乎并非总是如此:

#include <cstdio>
struct A
{
    int m[3];
};
struct B: A
{
    B():x(m[0]), y(m[1]), z(m[2]){}
    int& x;
    int& y;
    int& z;
};
int main(){
    printf("%u, %u\n", sizeof(A), sizeof(B));
    return 0;
}

输出:

12, 40

为什么 B 比 A 大这么多?

有没有其他方法可以访问,例如 B.m[0] 和 B.x?

【问题讨论】:

  • 你读错了。谜团已揭开。 ;-)
  • stackoverflow.com/questions/1179937/… 我从那里读到它,以及其他来源。
  • @Hassedev 这与函数堆栈上的引用有关,作为成员的引用是不同的野兽
  • 比那个答案的作者措辞有点粗心,你还没有仔细阅读。默认情况下,任何引用都需要内存。但在某些情况下可能会被优化掉。
  • Aaaand... 现在我再次阅读它,我注意到它们可能以多种不同的方式实现。好吧,另一个问题仍然有效:)

标签: c++


【解决方案1】:

引用就像一个指针,它不能为空,也不能“重新定位”(使其指向不同于最初指向的东西)。因此,我们可能期望引用占用与指针相同的空间量(尽管不能保证)。所以三个整数,4 个字节用于对齐,然后三个 8 字节指针将是 40 个字节,使您的示例完全合理。

你可以创建一个像B.x() 这样的方法来返回一个值而不占用更多空间。但是由于 C++ 缺少“属性”,所以您不能让 B.x 返回不占用空间的东西(即,您不能进行看起来像成员变量访问但行为像方法调用的东西)。

【讨论】:

    【解决方案2】:

    你解释错了。一个reference that is used purely locally can - and often is - eliminated by the optimizer。请注意,在它的生命周期内,我们仍然需要将它存储在某个地方(例如在寄存器中)。

    编译器不能像局部变量那样容易地预测对象的寿命,因此,成员引用实际上不能被替换和丢弃:有必要保存一个指针(4 字节或 8 字节)指向在对象生命周期内保持成员一致的实际内容。

    【讨论】:

      【解决方案3】:

      从我目前阅读的内容来看,似乎引用变量根本不应该占用任何内存。

      您应该进一步阅读;) 说真的,引用不是魔术。所以在现实世界中,对象必须以某种方式存储有关引用绑定到哪个对象的信息。因此,虽然从概念上讲,引用没有大小,但实际上它非常像指针,通常编译器只使用指针。与指针不同的行为(非空、不可重新赋值、无需取消引用)由编译器在编译时强制执行。

      所以你看到的基本上是 A 的大小加上填充加上三个指针的大小。我猜你在一个 64 位系统上,sizeof(int) 是 4,sizeof(void*) 是 8:

       12 bytes for the A subobject (4 for each int)
      + 4 bytes padding (to get to a multiple of 8 bytes)
      +24 bytes for the 3 references/pointers in B (8 for each one)
      --------------
       40 bytes total
      

      对于您的其他问题,给定B 类型的对象b,您可以直接访问b.m[0],因为它在A 中是公开的并且是公开继承的。在没有您遇到的引用开销的情况下给它另一个名称是不可能的。

      【讨论】:

      • 有一天我必须创建自己的语言,为变量使用别名;)或者也许只是一个用于添加别名的 c++ 预处理器。
      • 也许您可以为现有的开源编译器之一编写插件/扩展;)但话说回来,这些别名只会让阅读您的源代码的同事感到困惑。叫孩子的名字...
      猜你喜欢
      • 2018-05-19
      • 1970-01-01
      • 2012-05-28
      • 1970-01-01
      • 1970-01-01
      • 2018-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多