派生类比基类大,尽管它由引用变量组成
Derived class is bigger than base class even though it consists of reference variables
从我读到目前为止,似乎引用变量不应该占用任何内存。相反,它们被视为它们引用的完全相同的变量,但具有另一个名称。
然而,当我运行下面的代码时,似乎并不总是这样:
#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, %un", sizeof(A), sizeof(B));
return 0;
}
输出:12, 40
为什么B比A大那么多?
是否有其他方法可以访问,例如B.m[0]与B.x?
从我读到目前为止,似乎引用变量不应该占用任何内存。
你应该进一步阅读;)说真的,推荐信并不是魔法。所以在现实世界中,对象必须以某种方式存储有关引用绑定到的对象的信息。因此,虽然从概念上讲,引用没有大小,但它实际上非常像指针,通常编译器只使用指针。与指针不同的行为(非空,不可重赋值,不需要解引用)由编译器在编译时强制执行。
所以你看到的实际上是A的大小加上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
中是公共的并且是公共继承的。在不增加引用开销的情况下给它另一个名字是不可能的。
你理解错了。纯粹在局部使用的引用可以(而且经常被)被优化器消除。请注意,在它的生命周期内,我们仍然需要将它存储在某个地方(比如寄存器中)。
编译器不能像局部变量那样容易地预测对象的生命周期,因此,成员引用实际上不能被替换和丢弃:有必要保留一个指向实际内容的指针(4字节或8字节),以保持成员在对象生命周期内的一致性。
引用就像一个指针,不能为空,也不能被"重置"(使其指向与其最初指向的东西不同的东西)。因此,我们可能期望引用占用与指针相同的空间量(尽管这不能保证)。因此,三个int型,4个字节用于对齐,然后三个8字节指针将是40个字节,使您的示例非常合理。
您可以创建一个像B.x()
这样的方法来返回一个值,而不占用更多的空间。但是由于c++缺乏"属性",你不能让B.x
返回不占用空间的东西(即你不能让一些看起来像成员变量访问但行为像方法调用的东西)。
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- 多个"常量引用"变量可以共享同一个内存吗?
- 在 gtest 中初始化堆栈上的引用变量的隔离错误
- C++方法中的引用变量
- 作为赋值(增加引用变量)C++的左操作数所需的左值
- 使用更改此变量的函数在同一行中打印引用变量
- 将延迟变量分配给引用变量
- 如何通过引用获取引用变量的地址?
- 将引用变量传递给函数
- C++中引用变量的内存?
- 按名称存储和引用变量列表
- 返回一个C++引用变量 VS 返回一个变量
- c++ 在 if 语句中分配引用变量
- 引用变量何时合适,为什么?你能解释一下实际的语法和位置吗?
- C++ - 将一个变量分配给另一个变量和将变量分配给引用变量有什么区别?
- 在类范围内声明时,应在 C++14 中引用变量模板
- 当引用变量的引用"死亡"时,它会发生什么?
- 将非按引用变量分配给返回按引用的函数,反之亦然
- 引用变量如何存储在mem中
- 引用变量存储在哪里