При возврате объекта из функции может произойти один из следующих случаев, начиная с C ++ 11, при условии, что определены конструкторы перемещения и копирования (см. Также примеры в конце этого поста):
- it подходит для copy-elision , и компилятор выполняет RVO.
- он соответствует для copy-elision, а компилятор не выполняет RVO, но затем ...
- it соответствует использованию конструктора перемещения и перемещается.
- ничего из вышеперечисленного и конструктор копирования не используется.
Совет дляпервые 3 случая - не использовать явный std::move
, потому что перемещение выполняется в любом случае и может предотвратить возможное RVO, см., например, этот SO-post .
Однако в 4. case явное std::move
улучшит производительность.Но как человек, который свободно читает ни стандартный, ни получающийся ассемблер, требуется много времени, чтобы различать случаи 1-3 и 4.
Таким образом, мой вопрос: Есть лиспособ обработки всех вышеперечисленных случаев унифицированным способом, таким образом:
- RVO не затрудняется (случай 1)
- , если RVO являетсяне выполняется, используется конструктор перемещения (случаи 2,3 и 4)
- , если конструктор перемещения отсутствует, в качестве запасного варианта следует использовать конструктор копирования.
Вот несколько примеров, которые также можно использовать в качестве тестовых случаев.
Во всех примерах используется следующее определение класса помощника:
struct A{
int x;
A(int x_);
A(const A& a);
A(A&& a);
~A();
};
1.пример: 1.case, выполнено RVO, живая демонстрация , результирующий ассемблер :
A callee1(){
A a(0);
return a;
}
2.пример: 1.case, выполнено RVO, живая демонстрация , результирующий ассемблер :
A callee2(bool which){
return which? A(0) : A(1);
}
3.пример: 2.case, соответствует разрешению копирования, RVO не выполнен, live-демонстрация , результирующий ассемблер :
A callee3(bool which){
A a(0);
A b(1);
if(which)
return a;
else
return b;
}
4.пример: 3.case, не соответствует разрешению копирования (x
- это параметр-функция), но для перемещения live-демонстрация , результирующий ассемблер :
A callee4(A x){
return x;
}
5.пример: 4.case, без копирования или неявного перемещения (см. SO-post ), live-демонстрация , результирующий ассемблер :
A callee5(bool which){
A a(0);
A b(1);
return which ? a : b;
}
6.пример: 4.case, без копирования или неявного перемещения, live-демонстрация , результирующий ассемблер :
A callee6(){
std::pair<A,int> x{0,1};
return x.first;
}