int &&rri = 42;
int &&rri1 = rri;
rri是一个左值,rri1不能绑定一个左值。
int&& rri1 = static_cast<int&&>(rri);
但是为什么static_cast转换后就可以了呢?static_cast转换后的类型不还是int&&的吗?
int &&rri = 42;
int &&rri1 = rri;
rri是一个左值,rri1不能绑定一个左值。
int&& rri1 = static_cast<int&&>(rri);
但是为什么static_cast转换后就可以了呢?static_cast转换后的类型不还是int&&的吗?
static_cast之所以可以是因为表达式static_cast<int&&>(rri)
的value category是xvalue。相比之下表达式rri
是lvalue。这两个表达式的类型相同,均为int。
引用初始化是否合法取决于被初始化的引用类型和用于初始化的表达式的类型以及它的value category。
value category是表达式的一个属性(也可以理解成所有表达式都可以按value category归为三类)。
使用表达式的类型进行分析时,需要首先去掉它的所有引用,即如果直觉上某表达式的类型是int &&,那么分析时其类型要按int处理。
value category一种有五种
三种primary category: lvalue, prvalue, xvalue
两种mixed category: glvalue(lvalue, xvalue), rvalue(prvalue, xvalue)
只有prvalue或xvalue可以用于初始化右值引用,也就是rvalue。
因此要确定一个表达式是否能初始化某个引用,我们需要确定这个表达式属于哪个value category。
int &&rri = 42; \\ 表达式 42 是int rvalue(prvalue),可以初始化右值引用
int &&rri1 = rri; \\ 表达式 rri 是int lvalue,不可以初始化右值引用
int &&rri2 = static_cast<int&&>(rri); \\ 表达式`static_cast<int&&>(rri)`是int rvalue(xvalue),可以初始化右值引用
PS:更加完整的分析还要考虑到隐式转换,但你给出的例子几乎不涉及隐式转换,这部分就略去了。
3 回答2k 阅读✓ 已解决
2 回答3.9k 阅读✓ 已解决
2 回答3.2k 阅读✓ 已解决
1 回答3.2k 阅读✓ 已解决
1 回答2.7k 阅读✓ 已解决
3 回答3.5k 阅读
3 回答469 阅读✓ 已解决
左值 / 右值 是 表达式的值的属性,不是类型的属性,不与类型一一对应。它是由表达式的值的类型,与表达式的形式(得到这个值的过程)共同决定的。
rri
本身作为一个表达式,是一个左值。单独由一个变量组成的表达式叫做 id-expression (unqualified-id) 。unqualified-id 为函数、变量、类成员变量结果为左值;其它为右值(比如 enumerator)。
rri
是一个变量,结果为左值。static_cast<int&&>(rri)
的类型虽然与rri
相同,但是它是一个右值。static_cast<T>(v)
,仅当T
为 左值引用 或 对函数的右值引用 时,结果为左值。其余情况均为右值。C++ 标准里对每一种表达式形式,都详细定义结果何时为左值、何时为右值。
引用来自 C++17 draft n4659