右值引用还是左值?

12

我有一个类似于5年前发布的这个问题的问题:

为什么rvalue引用变量不是rvalue?

我的主要问题是为什么我可以这样做:

int&& k = 3;
k++;
但是我做不到这点:
(static_cast<int&&>(3))++;

我一直将右值引用解释为左值,因为右值引用变量是左值。但显然并非如此。有人能向我解释为什么(static_cast<int&&>(3))++;的结果是using rvalue as lvalue吗?

2个回答

11
混淆可能来自于r-valuer-value引用的区别。前者是一个值类别,仅适用于表达式,而后者是一个类型,适用于变量(技术上需要某种类型的r-value引用,例如r-value引用到int)。
因此,您展示的片段之间的区别实际上与变量类型无关,而与表达式值类别有关。后缀operator++要求操作数的值类别为l-value,而不管操作数的类型如何。
k++中,表达式k是l-value(粗略地说,它有一个名称),这是它的值类别。变量k的类型是r-value引用,但这没问题。
(static_cast<int&&>(3))++中,表达式static_cast<int&&>(3)是一个r-value(它没有名称),这是它的值类别。无论static_cast<int&&>类型是什么(它是int),值类别都是错误的,因此您会收到错误消息。
请注意,错误消息using rvalue as lvalue指的是正在使用的表达式的值类别。它与变量的类型无关。

5
需要注意的是,表达式不能具有引用类型。变量 k 的类型为 int &&,但表达式 k 的类型只是 int(并且该表达式是左值)。这也意味着 static_cast<int&&>(3) 的类型是 int 而不是 int && - HolyBlackCat
1
想要了解更多的人可以阅读这篇不错的文章:https://en.cppreference.com/w/cpp/language/value_category - bolov
2
@cigien 看起来不错。我会在那里留下我的评论,因为“表达式不能有引用类型”是我刚开始学习时让我恍然大悟的原因。 - HolyBlackCat
1
@cigien 我对“它没有名称,所以它是rvalue”这个参数有点困惑。为什么 (static_cast<int&>(k))++ 能够工作,其中 k 是某个 int 变量?我知道该表达式返回 k 的引用,而引用被定义为对象的另一个名称,但是 static_cast<int&>static_cast<int&&> 之间有什么区别呢?两者都返回引用,对吧?总之,为什么表达式 static_cast<int&> 有一个名称? - domdrag
1
@cigien 是的,我理解了那部分。我不理解的部分是,我怎么知道 static_cast<int&&>(3) 是右值?你说过原因是它没有名字。这也有道理。但是,对我来说不合理的是为什么表达式 static_cast<int&>(k) 有一个名字? - domdrag
显示剩余6条评论

0
因为rvalue引用变量是lvalue 根据cppreference 引用自cppreference的内容如下: lvalue 即使变量的类型是rvalue引用,由其名称组成的表达式仍然是lvalue表达式(但请参见可移动的表达式);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接