Всегда ли правильный операнд присваивания преобразуется в r-значение?

Я хотел бы получить разъяснения по этому конкретному случаю:

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

Test() = default;
}

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

«a» является lvalue, однако теперь это правый операнд присваивания. Означает ли это, что он превращается в значение?

Этот код не компилируется:

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

Поскольку ссылка lvalue не может привязываться к rvalue, означает ли это, что здесь не происходит преобразование? Если это так, то когда происходит неявное преобразование lvalue в rvalue? (Кроме случая оператора + с примитивными типами)

3

Решение

«a» является lvalue, однако теперь это правый операнд присваивания. Означает ли это, что он превращается в значение?

Короче да. Во всех версиях и черновиках стандарта C ++ одно из стандартных преобразований называется преобразованием «lvalue-to-rvalue».

Это применимо в первом случае, который вы описываете.

Поскольку ссылка lvalue не может привязываться к rvalue, означает ли это, что здесь не происходит преобразование? Если это так, то когда происходит неявное преобразование lvalue в rvalue? (Кроме случая оператора + с примитивными типами)

Во втором случае вы объявили / определили operator=(Test &&) который принимает ссылку Rvalue, которая подавляет генерацию operator=(const Test &), В C ++ 11 и более поздних версиях operator=(Test &&) без одного из operator=(Test &) или же operator(const Test &) предотвращает использование lvalue с правой стороны (как в вашем примере, a = b).

Что косвенно означает, что в этом случае преобразование lvalue в rvalue не используется.

1

Другие решения

Это lvalue, 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

Если вы хотите получить rvalue, вы можете написать это:

Test a;
Test b;
a = Test(); //Uses move operator
2

В вашем случае нет преобразования lvalue в rvalue (игнорирование кодов в определении operator=).

Здесь вы используете перегруженные операторы и в соответствии с [Expr.pre] / 2,

Перегруженные операторы подчиняются правилам синтаксиса и порядку оценки, указанным в [expr.compound], но требованиям типа операнда и категория стоимости заменяются правилами для вызова функции.

Таким образом, он не требует, чтобы правильный операнд был prvalue, следовательно, нет преобразования lvalue в rvalue.

1
По вопросам рекламы [email protected]