Являются временными lvalue вариантом использования std :: move

У меня такой class:

class Widget
{
public:
    Widget(A const& a) { /* do something */ }
    Widget(A&& a) { /* do something */ }
};

Что я могу использовать так:

A a{};
Widget widget{a};

Если бы я пришел к выводу, что a мне больше не нужен, я мог бы позвонить:

Widget{std::move(a)};

Но что теперь, если мне нужен A объект только для построения widget? Я бы сделал это:

Widget widget{A{}};

or

Widget widget{std::move(A{})}; 

person hgiesel    schedule 10.03.2016    source источник
comment
Я не вижу временного значения lvalue. A{} - это rvalue, поэтому разрешение перегрузки подхватит конструктор перемещения.   -  person juanchopanza    schedule 10.03.2016
comment
Я думаю, вы хотели написать Widget widget{std::move(a)}; в случае или.   -  person nwp    schedule 10.03.2016
comment
Тогда почему A{} = A{}; является допустимым выражением?   -  person hgiesel    schedule 10.03.2016
comment
Почему бы и нет? Вы думаете, что rvalue не может появиться в левой части уравнения, и поскольку A{} = A{} является допустимым, это должно означать, что A{} не является rvalue? В этом случае забудьте о rvalue и lvalue в смысле слева и справа от присваивания, что просто не выполняется в C ++.   -  person nwp    schedule 10.03.2016
comment
@hgiesel: Это C ++, меня не удивило бы, если бы это оказалось декларацией: P   -  person Lightness Races in Orbit    schedule 10.03.2016
comment
@nwp: int(42) = 43; error: lvalue требуется в качестве левого операнда присваивания Независимо от того, применяется ли оно здесь, такое правило действительно существует.   -  person Lightness Races in Orbit    schedule 10.03.2016
comment
На самом деле это интересно: int{42} = 43; ошибка: в качестве lvalue используется временное значение, хе. В любом случае, я думаю, что это работает только потому, что A не является встроенным.   -  person Lightness Races in Orbit    schedule 10.03.2016
comment
@BarryTheHatchet да, вы можете вызывать неконстантные методы для объектов rvalue, operator= не является исключением   -  person Slava    schedule 10.03.2016
comment
@nwp именно так, я знаю, что lvalues ​​не всегда должны быть на lhs, но я думал, что вы не можете назначать rvalue   -  person hgiesel    schedule 10.03.2016
comment
@hgiesel: вы не можете присвоить rvalue встроенным типам (не забудьте в этом предложении). Но A - это класс, поэтому правила значительно более мягкие.   -  person Lightness Races in Orbit    schedule 10.03.2016
comment
Что касается того, почему A{} = A{}; работает, см. Следующее: stackoverflow.com/questions/10897799/   -  person NathanOliver    schedule 10.03.2016
comment
@BarryTheHatchet Честно говоря, int{42} = 43; должен компилироваться. Нет никаких веских причин разрешать Int{42} = 43; и запрещать int{42} = 43;, кроме того, никто не считал это достаточно важным, чтобы изменить это в стандарте.   -  person nwp    schedule 10.03.2016
comment
@nwp Это потому, что встроенные типы не являются типами классов, поэтому у них нет функций-членов.   -  person NathanOliver    schedule 10.03.2016
comment
@NathanOliver Это не имеет смысла. Это все еще может быть разрешено без функций-членов. Это предмет языкового дизайна.   -  person juanchopanza    schedule 10.03.2016
comment
@BarryTheHatchet технически A{} = A{}; можно рассматривать как A{}.operator=( A{} );   -  person Slava    schedule 10.03.2016
comment
@Slava: Да, спасибо, я в курсе.   -  person Lightness Races in Orbit    schedule 10.03.2016


Ответы (1)


Временное значение - это rvalue; нет никаких «временных lvalue». Widget widget{A{}}; вызовет Widget(A&& a), поскольку A{} является временным. std::move используется, когда у вас есть lvalue и вы хотите сделать его rvalue, как вы это делаете с:

A a{};
Widget widget{std::move(a)};

Еще одна причина использовать это, если вы находитесь в функции, которая принимает rvalue, и вы хотите переместить ее в конструктор. С функцией

Widget foo(A&& a);

a - это l-значение в теле функции. Если вы хотите преобразовать его обратно в rvalue, вам нужно будет использовать std::move, например

Widget foo(A&& a)
{
    Widget widget{std::move(a)};
}
person NathanOliver    schedule 10.03.2016