В Foo(2)
целое число является rvalue, и необходим ссылочный конструктор rvalue из int&&
.
В случае
Foo f = num; // custom constructor
Конструктор rvalue не вызывается,потому что именованные значения никогда не рассматриваются как rvalue.Вы должны вызвать std::move(num)
, чтобы заставить его работать.
Стандарт определяет это таким образом, чтобы избежать путаницы в случаях, когда именованные значения перемещаются неожиданно и используются позже.Вы должны четко указывать перемещение, даже если переменная является ссылкой на rvalue.
edit
Согласно cppreference компилятор c ++ 17 должен исключить копию /Конструктор перемещения (т.е. он не должен вызывать или требовать наличия конструктора копирования / перемещения в этом случае, и поэтому вы видите только конструктор из int&&
):
Foo f4(Foo(2));
Вот цитатаиз cppreference (который не так хорош, как стандарт, но достаточно близок):
языковые правила гарантируют, что операция копирования / перемещения не выполняется, даже концептуально:
При инициализации переменной, когда выражение инициализатора является prvalue того же типа класса (игнорируя квалификацию cv), что и тип переменной:
T x = T (T (T ())));// только один вызов конструктора по умолчанию для T, чтобы инициализировать x