从我到目前为止所读到的,似乎参考变量根本不应该占用任何内存。相反,它们被视为它们引用的完全相同的变量,但具有另一个名称。
但是,当我运行以下代码时,似乎并非总是如此:
#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?
答案 0 :(得分:7)
从我到目前为止所读到的,似乎参考变量根本不应该占用任何内存。
你应该进一步阅读;) 说真的,引用并不神奇。所以在现实世界中,对象必须以某种方式存储关于引用绑定到哪个对象的信息。因此,从概念上讲,引用没有大小,它实际上非常像指针,通常编译器只使用指针。在编译时,编译器强制执行与指针(非空,不可重新分配,无需取消引用)的行为。
所以你看到的基本上是A plus padding的大小加上三个指针的大小。我猜您使用的是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
中已公开并已公开继承。在没有您遇到的参考开销的情况下给它另一个名称是不可能的。
答案 1 :(得分:4)
你在解释错误的事情。一个 reference that is used purely locally can - and often is - eliminated by the optimizer 。请注意,我们仍然需要在其生命周期中将其存储在某个地方(例如寄存器中)。
编译器无法像局部变量一样容易地预测对象的生命周期,因此,成员引用实际上不能被替换和丢弃:必须将指针(4字节或8字节)保存到在对象生命周期内保持成员一致的实际内容。
答案 2 :(得分:2)
引用就像一个指针,它不能为空,永远不能“重新安置”(指向不同于它最初指向的东西)。因此,我们可能期望引用占用与指针相同的空间量(尽管这不能保证)。因此三个整数,4个字节用于对齐,然后三个8字节指针将是40个字节,使您的示例完全合理。
您可以使B.x()
之类的方法返回值而不占用更多空间。但是由于C ++缺少“属性”,你不能让B.x
返回不占空间的东西(即你不能制作看起来像成员变量访问但行为类似于方法调用的东西)。