为什么rvalue / const引用有内存地址和大小?

时间:2016-04-17 12:22:32

标签: c++ reference

我到处都读到引用不是对象,它们只是别名而且它们在内存中没有位置

int x = 256;
int& rx = x;

std::cout << x << " " << &x << std::endl;       // Output: 256  0x15FAB0
std::cout << rx << " " << &rx << std::endl;     // Output: 256  0x15FAB0

// seems legit ... fair enough ...

现在考虑以下

const int& r1 = 8;      // lvalue ref to const int
int&& r2 = 32;          // rvlaue ref to int
const int&& r3 = 128;   // rvalue ref to const int

std::cout << r1 << " " << &r1 << std::endl;     // Output: 8     0x15FA8C
std::cout << r2 << " " << &r2 << std::endl;     // Output: 32    0x15FA74
std::cout << r3 << " " << &r3 << std::endl;     // Output: 128   0x15FA5C

// and ...

std::cout << sizeof(r1) << std::endl;   // Ouput: 4
std::cout << sizeof(r2) << std::endl;   // Ouput: 4
std::cout << sizeof(r3) << std::endl;   // Ouput: 4

那么为什么这些引用的行为类似于对象,它们确实具有值,内存地址和大小......它们是否与引用规则不同? 他们是在堆栈上还是在其他地方?

5 个答案:

答案 0 :(得分:6)

我猜你真正的问题是“当rvalue / const引用没有引用具有名称的任何东西时,它会在哪里发生?”

const int& r1 = 8;      // lvalue ref to const int
int&& r2 = 32;          // rvlaue ref to int
const int&& r3 = 128;   // rvalue ref to const int

在上述所有三种情况下,编译器在临时位置分配空间,将值放在那里,并为您提供该值的引用。允许编译器执行此操作,因为它可以保证临时位置保持只读。

这就是你的引用获取地址的方式 - 对象(8,32,128)仍然存在,因为编译器会为你创建它们。这些隐藏对象的地址成为引用的地址;这些隐藏对象的大小由sizeof运算符报告。

答案 1 :(得分:3)

引用的sizeof()不会为您提供引用本身的大小,而是引用引用所引用的sizeof()

struct foo {
    int a[128];
};

foo bar;
foo &baz=bar;

std::cout << sizeof(baz) << std::endl;

你在这里得到一个相当大的sizeof()。显然,这不是引用的大小,而是引用的对象的大小。

这适用于左值和左值参考。

答案 2 :(得分:2)

引用具有地址和大小,因为它绑定到临时。因此,临时的生命周期将延长以匹配参考的生命周期。

§12.2第4,5段明确涵盖了这一点:

  

4有两种情况,临时表演在不同于完整表达结束时被摧毁。   第一个上下文是调用默认构造函数来初始化数组的元素。如果   构造函数有一个或多个默认参数,破坏默认情况下创建的每个临时值   在构造下一个数组元素之前,参数是按顺序排序的。

     

5 第二个上下文是指引用绑定到临时 .117引用的临时值   绑定或临时是绑定引用的子对象的完整对象仍然存在   参考的生命周期除外:...

答案 3 :(得分:1)

引用本质上是相同值的另一个名称。正如您在测试中看到的那样,它们具有与原始值相同的大小和地址。如果您创建一个值并直接引用它,那么引用也将是该值的名称。

答案 4 :(得分:1)

int x = 256;
int& rx = x;
     

[...]

const int& r1 = 8;      // lvalue ref to const int
int&& r2 = 32;          // rvlaue ref to int
const int&& r3 = 128;   // rvalue ref to const int

这两个例子之间没有太大区别。在第一个示例中,您将一个引用(rx)声明为之前已命名的对象(x)。在第二个示例中,您的三个引用(r1r2r3)引用了在每个引用初始化期间创建的临时对象。

  

那么为什么这些引用表现得像对象一样,它们确实有值,   内存地址和大小...

他们没有。只是这里的对象只是由引用命名而不是其他任何东西。您的sizeof和地址运算符仍然适用于这些对象。