【问题标题】:Converting between rvalue and lvalue在右值和左值之间转换
【发布时间】:2017-10-31 16:51:00
【问题描述】:

我试图理解并阅读右值不能转换为左值。下面的就好了

int x = 1;     // x is an lvalue
int y = 2;     // y is an lvalue
int z = x + y; // the "+" needs rvalues, so x and y are converted to rvalues 
               //(from lvalues) and an rvalue is returned

如果我这样做了

x = 5;
y = 6;

x 和 y 不是转换为左值(从右值)吗?

编辑:What are rvalues, lvalues, xvalues, glvalues, and prvalues? 中的问题几乎没有提及转换,也没有示例可以解释。

【问题讨论】:

标签: c++ rvalue lvalue


【解决方案1】:

准确地说出我们正在谈论的内容很重要。

  • 在 C++ 中,表达式具有类型,可以是左值或右值(值类别)
  • 隐式转换当一个表达式(类型、值类别)出现在预期不同(类型、值类别)的上下文中时。
  • 显式转换使用语言的强制转换运算符之一,将一个(类型,值类别)的子表达式作为操作数,并产生一个不同(类型,值类别)的表达式结果。

左值或xvalue可以隐式转换为prvalue;由于历史原因,这被称为左值到右值的转换。线

int z = x + y;

作为这种隐式转换的一个例子。正如评论所解释的,内置的 + 运算符期望 prvalues 作为其操作数,但我们提供了左值,因此会发生隐式转换。

左值也可以显式转换为 xvalue:

std::string s1 = static_cast<std::string&&>(s2);  // i.e., std::move(s2)

这里s2 是一个左值,但我们要确保初始化器是一个xvalue,以便使用移动构造函数,因此我们执行显式转换。

右值既不能隐式也不能显式转换为左值。例如,以下内容无法编译:

3++;

因为++ 运算符需要一个左值,而我们提供了一个右值。以下内容也不会编译,我们尝试将右值显式转换为左值:

static_cast<int&>(3)++;

(注意:3 的类型是int,而不是const int。常量不是我们不能修改3的原因。)

在显示的分配中实际上没有发生转换:

x = 5;
y = 6;

因为在分配给int 左值时,prvalue预计作为右手操作数,并且已经提供了prvalue。虽然我们正在做某种以右值作为源,以左值作为目标的操作,但这不是根据语言规则的转换。

【讨论】:

    【解决方案2】:

    左值有点意思是“地址”。 Rvalue 有点意思是“价值”。 表达式 是左值或右值。由于表达式x 是一个左值,但是,在表达式z = x + y; 中,+ 运算符需要数据,所以x 和y 被取消引用。也就是说,获取它们地址处的值,并将这些右值加在一起,产生一个等于它们总和的右值。赋值运算符需要左边有一个左值,右边有一个右值。它将右边的值放到左边的地址中,所以z没有被解引用,是一个左值。

    除非你知道它的上下文,否则不能说像x 这样的变量是左值或右值。

    【讨论】:

    • 表达式 x总是是一个左值。 statement int x; 将 x 定义为 int 类型的对象,statement int x = 1; 定义 x 并对其进行初始化。
    • IMO 当我们不谈论指针时,使用指针术语会令人困惑。此外,x 绝对是一个左值,无论上下文如何。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-24
    • 1970-01-01
    • 1970-01-01
    • 2013-07-12
    • 1970-01-01
    • 2014-01-17
    • 2020-09-19
    相关资源
    最近更新 更多