Итак, после поиска семантики перемещения я вижу, что общий консенсус должен пройти по стоимости, когда вы намерены передать право собственности. Но в Скотт Мейер говорит об универсальных ссылках Я заметил, что std::vector::push_back
имеет 2 перегрузки:
void push_back( const T& value );
void push_back( T&& value );
Итак, я подумал про себя: не хватит ли void push_back( T value );
? Я попросил несколько человек, которые в конечном итоге приводят к следующему тестовому примеру:
#include <memory>
#include <iostream>
#include <type_traits>
struct A
{
A() { std::cout << "A Default constructor\n"; }
A(const A &) { std::cout << "A Copy\n"; }
A(A &&) { std::cout << "A Move\n"; }
};
std::aligned_storage<sizeof(A)> contents;
A& alias = *reinterpret_cast<A*>(&contents);
void ByVal(A a)
{
new (&contents) A(std::move(a));
alias.~A();
}
void ByLCRef(A const& a)
{
new (&contents) A(a);
alias.~A();
}
void ByRRef(A&& a)
{
new (&contents) A(std::move(a));
alias.~A();
}
int main()
{
A a;
std::cout << "\n";
std::cout << "ByVal(a);\n";
ByVal(a);
std::cout << "ByVal(std::move(a));\n";
ByVal(std::move(a));
std::cout << "ByVal(A());\n";
ByVal(A());
std::cout << "ByLCRef(a);\n";
ByLCRef(a);
std::cout << "ByRRef(std::move(a));\n";
ByRRef(std::move(a));
std::cout << "ByRRef(A());\n";
ByRRef(A());
}
Что дает следующее:
A Default constructor
ByVal(a);
A Copy
A Move
ByVal(std::move(a));
A Move
A Move
ByVal(A());
A Default constructor
A Move
ByLCRef(a);
A Copy
ByRRef(std::move(a));
A Move
ByRRef(A());
A Default constructor
A Move
Как вы можете видеть, ByVal
производит 1 дополнительный ход по сравнению с парой эталонных перегрузок. Поэтому вопрос: стоит ли это? Когда вы создадите две перегрузки вместо одного простого прохода по функции значений?