3

我想澄清一下这个特殊情况:

class Test
{
    Test& operator=(const Test& copy)
    {
      ...
    }

    Test() = default;
}

Test a;
Test b;
b = a; //Is "a" converted to an rvalue?

"a" 是一个左值,但它现在是赋值的右手操作数。这是否意味着它被转换为右值?

此代码无法编译:

class Test
{
    Test& operator=(Test&& copy) 
    {
      ...
    }

    Test() = default;
}

Test a;
Test b;
a = b; //Error

但是这个可以:

class Test
{
    Test& operator=(Test& copy) 
    {
      ...
    }

    Test() = default;
}

Test a;
Test b;
a = b; //OK

由于左值引用不能绑定到右值,这是否意味着这里没有发生转换?如果是这种情况,什么时候会发生隐式左值到右值的转换?(除了具有原始类型的 operator+ 的情况)

4

3 回答 3

2

在您的情况下,没有左值到右值的转换(忽略 的定义中的代码operator=)。

在这里,您使用重载运算符并根据[expr.pre]/2

重载运算符遵循 [expr.compound] 中指定的语法和计算顺序规则,但操作数类型和值类别的要求被函数调用规则所取代。

所以它不需要正确的操作数是纯右值,因此没有左值到右值的转换。

于 2018-04-25T13:53:00.033 回答
2

这是左值,b = a;调用复制运算符

class Test
{
    Test& operator=(const Test& copy)
    {
      ...
    }

    Test() = default;
}

Test a;
Test b;
b = a; //Is "a" converted to an rvalue?

错误,因为您的复制构造函数和复制运算符不是由编译器生成的,因为声明了移动运算符

class Test
{
    Test& operator=(Test&& copy) 
    {
      ...
    }

    Test() = default;
}

Test a;
Test b;
a = b; //Error

如果你想获得右值,你可以这样写:

Test a;
Test b;
a = Test(); //Uses move operator
于 2018-04-25T12:46:08.683 回答
1

"a" 是一个左值,但它现在是赋值的右手操作数。这是否意味着它被转换为右值?

简而言之,是的。在 C++ 标准的所有版本和草案中,其中一种标准转换称为“左值到右值”转换。

这适用于您描述的第一种情况。

由于左值引用不能绑定到右值,这是否意味着这里没有发生转换?如果是这种情况,什么时候会发生隐式左值到右值的转换?(除了具有原始类型的 operator+ 的情况)

在第二种情况下,您已经声明/定义了一个operator=(Test &&)接受右值引用的 an,它禁止生成 an operator=(const Test &)。在 C++11 及更高版本中,声明 aoperator=(Test &&)没有operator=(Test &)or会operator(const Test &)阻止在右侧使用左值(如您的示例中所示a = b)。

这间接地意味着在这种情况下不使用左值到右值的转换。

于 2018-04-25T13:23:49.697 回答