Всегда ли правильный операнд присваивания преобразуется в 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 ответа
В вашем случае нет преобразования lvalue в rvalue (игнорирование кодов в определении operator=
).
Здесь вы используете перегруженные операторы и в соответствии с [expr.pre] / 2,
Перегруженные операторы подчиняются правилам синтаксиса и порядка оценки, заданным в [expr.compound], но требования типа операнда и категории значения заменяются правилами для вызова функции.
Таким образом, он не требует, чтобы правильный операнд был prvalue, следовательно, нет преобразования lvalue в rvalue.
Это 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
"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 не используется.