考虑下面的最小示例:
#include<utility>
struct S { };
int main() {
S s;
std::move(s) = S{};
}
它编译没有错误。
如果我改用非类类型,则会出现错误。
例如,以下代码无法编译:
#include<utility>
int main() {
int i;
std::move(i) = 42;
}
枚举,作用域枚举等也一样。
错误(来自GCC)是:
使用xvalue(右值引用)作为左值
这背后的原理是什么?
我想这是正确的,但是我想了解使用非类型类的所有类型执行此操作的原因是什么。
我正在尝试通过一系列指向标准的链接来回答我自己的问题。
我非常确定我会写出非常错误的内容,并且有人会来跟我打招呼。
好吧,我尽力解释了如何从标准中推导出问题中所描述的内容。
如果需要,可以随意投票,但是请让我知道出了什么问题,以便能够解决问题并理解错误。
谢谢你。
3.9 / 8(类型):
一个 对象类型 是一个(可能CV修饰)类型不函数类型,不是引用类型,而不是 CV空隙。
5.2.2 / 10(表达式,函数调用):
如果结果类型是对对象类型的右值引用,则函数调用为x值
因此,在两种情况下std::move
都是xvalue表达式。
5.18 / 3(任务):
如果左操作数不是类类型,则将表达式隐式转换为左操作数的cv不合格类型。
这不会添加有用的信息,但这是为了完整性。
4.1 / 2(左值到右值转换):
否则,如果T具有类类型,则转换从glvalue复制初始化T类型的临时对象,并且转换结果是该临时对象的prvalue。
否则,glvalue指示的对象中包含的值就是prvalue结果。
其余的由12.2(临时对象)完成。
因此,正如@xaxxon在评论中提到的那样,我实际上是在尝试做(让我写)42 = 0;
,它在C ++中不是有效的表达式。
正如@bogdan的注释中正确指出的,在这种情况下要参考的标准的正确部分是5.18 / 1(赋值):
全部都需要可修改的左值作为其左操作数[...]
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句