Правильный ли операнд присваивания всегда преобразуется в значение? - PullRequest
0 голосов
/ 25 апреля 2018

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

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

    Test() = default;
}

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

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

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

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не может привязаться к r-значению, значит ли это, что здесь не происходит преобразование?Если это так, то когда происходит неявное преобразование lvalue в rvalue?(Кроме случая оператора + с примитивными типами)

Ответы [ 3 ]

0 голосов
/ 25 апреля 2018

«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 не используется.

0 голосов
/ 25 апреля 2018

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

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

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

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

0 голосов
/ 25 апреля 2018

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

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

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