取右值引用的地址是否合法?为何不是指向引用的指针?
结论先行:完全合法,但你误解了&r的本质——它并不是“取引用的地址”,因为引用根本不是独立对象,不存在所谓“指向引用的指针”。
拆解你的代码行为
先看这段代码:
#include <iostream> int main() { int a1 = 1; int a2 = 2; int&& r = a1 + a2; // 绑定临时对象的右值引用 r++; std::cout << r << std::endl; int* p = &r; // 这里不是指向引用的指针 std::cout << &r << " " << p << " " << *p << std::endl; *p++; std::cout << &r << " " << p << " " << *p << std::endl; }
右值引用的核心特性:临时对象续命
a1+a2的结果是一个临时int对象(右值),当你用右值引用r绑定它时,C++标准会自动延长这个临时对象的生命周期,让它和r的生命周期保持一致。此时r只是这个临时对象的别名——引用本身不占用内存空间,它只是对底层对象的另一个称呼,不存在独立的“引用实体”。
&r到底取的是什么地址?
当你写&r时,编译器会自动将其解析为取r所绑定的那个临时int对象的地址,而不是取引用本身的地址(因为引用没有自己的地址)。所以int* p = &r实际上是让指针p指向了那个被续命的临时int对象,这完全符合C++规则,是合法操作。
对应cppreference说明的正确理解
cppreference那段话:
Because references are not objects, there are no arrays of references, no pointers to references, and no references to references
这段话的意思是:引用不是独立的对象,因此不存在“引用数组”“指向引用的指针”“引用的引用”这些类型——你根本无法声明int&*(指向int引用的指针)这种类型。但你的代码里的int* p是指向int对象的指针,和“指向引用的指针”完全是两回事,所以和这段说明没有冲突。
代码里的坑点
最后提一句:代码中的*p++;是危险操作。p++会让指针移动到临时对象之后的内存区域,此时*p访问的是未定义的内存空间,属于未定义行为,运行时可能输出垃圾值甚至导致程序崩溃,这部分要避免。
内容的提问来源于stack exchange,提问作者vtm11

