Передать значение или rvalue-ref

Для перемещенных классов есть разница между этими двумя?

struct Foo {
typedef std::vector<std::string> Vectype;
Vectype m_vec;
//this or
void bar(Vectype&& vec)
{
   m_vec = std::move(vec);
}
//that
void bar(Vectype vec)
{
    m_vec = std::move(vec);
}
};
int main()
{
   Vectype myvec{"alpha","beta","gamma"};
   Foo fool; 
   fool.bar(std::move(myvec));
}

Я понимаю, что если вы используете lvalue myvec, вам также необходимо ввести const Vectype& версию Foo::bar(), так как Vectype&& не будет связываться. В стороне, в случае с rvalue, Foo::bar(Vectype) построит вектор, используя конструктор перемещения или лучше, но все же вернет копию вместе, увидев, что vec является rvalue (не так ли?). Таким образом, есть ли веская причина не предпочитать вместо объявления lvalue и rvalue объявление значения? (Рассмотрим, что мне нужно скопировать вектор в переменную-член в любом случае.)

Ответ 1

Функция pass-by-value является достаточной (и эквивалентной), если тип аргумента имеет эффективный конструктор перемещения, который в этом случае истинен для std::vector.

В противном случае использование функции pass-by-value может ввести дополнительную конструкцию копирования по сравнению с использованием функции pass-by-rvalue-ref.

См. ответ fooobar.com/questions/540636/... к связанному с ним вопросу Нужно ли мне перегружать методы, принимающие ссылку const lvalue для ссылок rvalue явно?.

Ответ 2

Версия pass-by-value допускает аргумент lvalue и делает его копию. Версия rvalue-reference не может быть вызвана с аргументом lvalue.

Используйте const Type&, когда вам не нужно вообще изменять или копировать аргумент, используйте pass-by-value, когда вы хотите модифицируемое значение, но вам все равно, как вы его получите, и используйте Type& и Type&& перегружает, когда вам нужно что-то немного отличающееся в зависимости от контекста.

Ответ 3

Да, первый (Vectype&& vec) не будет принимать объект const или просто lvalue.

Если вы хотите сохранить объект внутри, как и вы, лучше скопировать (или переместить, если вы передадите rvalue) в интерфейсе, а затем переместить, как и в своем втором примере.