C++ 成员引用是否填充类?或者它们只是比非成员引用更大?

C++ 成员引用是否填充类?或者它们只是比非成员引用更大?,c++,C++,我在玩一些对模板基本成员代码的引用。出于好奇,我想知道编译器是否在幕后以某种方式优化了我的引用(因为每次引用都指向父类中相同的变量)。我决定用一个简单的sizeof()测试来告诉我。令我大吃一惊的是,仅仅引用我继承的类的3个float成员就将我的类内存占用增加了333%。这使我非常惊讶和困惑 经过一番摆弄,我甚至不知道发生了什么(但我怀疑我是在装傻) 代码:(在Ubuntu 14.04上使用GCC4.8.2在代码::Blocks 13.12中编译) #包括 模板 类数组{ 公众: FooArra

我在玩一些对模板基本成员代码的引用。出于好奇,我想知道编译器是否在幕后以某种方式优化了我的引用(因为每次引用都指向父类中相同的变量)。我决定用一个简单的sizeof()测试来告诉我。令我大吃一惊的是,仅仅引用我继承的类的3个float成员就将我的类内存占用增加了333%。这使我非常惊讶和困惑

经过一番摆弄,我甚至不知道发生了什么(但我怀疑我是在装傻)

代码:(在Ubuntu 14.04上使用GCC4.8.2在代码::Blocks 13.12中编译)

#包括
模板
类数组{
公众:
FooArray(){
对于(尺寸i=0;istd::cout一个浮点数是4字节,一个引用是8字节。因此,一个由3个浮点数组成的数组将是12字节。唯一不重要的位是您的
Inherit3Ref
,它将如下所示:

float[3];
*** padding to 8 byte boundary ***
float &[3];
因此,12个字节用于浮点数+4个字节额外的填充+24个字节用于引用,使其成为40。如果您想避免填充,您可以将类打包-这将使您减少到36个字节


不知道为什么称之为“荒谬”-它必须至少是36…

一个浮点数是4字节,一个引用是8字节。因此一个3个浮点数的数组将是12字节。唯一不重要的位是您的
Inherit3Ref
,它将如下所示:

float[3];
*** padding to 8 byte boundary ***
float &[3];
因此,12个字节用于浮点数+4个字节额外的填充+24个字节用于引用,使其成为40。如果您想避免填充,您可以将类打包-这将使您减少到36个字节


不确定为什么称之为“荒谬”-它肯定至少必须是36…

编译器必须添加填充以确保任何成员变量都正确对齐。
float
具有大小4和对齐4,而引用和指针(指向任何对象)通常具有大小8(在64位计算机上)和对齐8。因此:

struct foo {
  float m_data[3];             // size 3*4=12   begin=0   end=12
  float&a;                     // size 8        begin=16  end=24   NOTE: 4 unused bytes
};
(另请注意

float&a,b;
相当于

float&a;
float b;
但不是

typedef float&float_ref;
float_ref a,b;

因此,为了清晰起见,最好避免使用这种符号)

编译器必须添加填充,以确保任何成员变量都正确对齐。
float
的大小为4,对齐方式为4,而引用和指针(指向任何对象)的大小通常为8(在64位计算机上)和对齐方式为8。因此:

struct foo {
  float m_data[3];             // size 3*4=12   begin=0   end=12
  float&a;                     // size 8        begin=16  end=24   NOTE: 4 unused bytes
};
(另请注意

float&a,b;
相当于

float&a;
float b;
但不是

typedef float&float_ref;
float_ref a,b;

因此,为了清楚起见,最好避免使用这种表示法。

您弄错了:填充不是16字节边界,而是8字节边界,因为
alignof(float&==8
。在这种情况下,8字节边界也是16字节边界。@Walter oops.typo?:)值得注意的是
sizeof(float&)
在他的输出中是4,这表明它是一台32位机器,所以在OP的情况下引用似乎不是8字节。除了cdhowie指出的,我的输出显示
sizeof(float&)
返回4。刚刚测试的
alignof(float&)
它还返回4。当所有变量的大小和对齐方式都是4字节时,为什么类要填充到8字节边界?你搞错了:填充不是到16字节边界,而是到8字节边界,因为
alignof(float&)==8
。在这种情况下,8字节边界也是16字节边界。@Walter oops.typo?:)值得注意的是,他的输出中的
sizeof(float&)
是4,表示它是一台32位机器,所以在OP的情况下引用似乎不是8字节。除了cdhowie指出的,我的输出显示
sizeof(float&)
返回4。刚刚测试过的
alignof(float&)
它也返回4。当所有变量的大小和对齐方式都是4字节时,为什么类应该填充到8字节的边界?感谢您的参考声明说明,我没有意识到语法是这样工作的。但是,请注意
sizeof(float&)
返回4。刚刚测试后,
alignof(float&)
也返回4。这仅仅是我的另一个编程错误吗?奇怪的是,包装参考大小4会使类大小为8,而包装float大小4会使类大小为4。
sizeof(float&)
不会给出引用的大小,但会给出引用对象的大小。引用是奇怪的野兽,几乎总是衰减到引用的类型。请尝试
sizeof(std::reference\u包装器)
获取引用的实际大小。哇,这是一种很酷的类型……我喜欢标准库!非常感谢您的帮助@Walter。感谢您提供引用声明