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