c++ - ¿La devolución por referencia de valor es más eficiente?
c++11 rvalue-reference (2)
por ejemplo:
Beta_ab&&
Beta::toAB() const {
return move(Beta_ab(1, 1));
}
Puede ser más eficiente, por ejemplo, en un contexto un poco diferente:
template <typename T>
T&& min_(T&& a, T &&b) {
return std::move(a < b? a: b);
}
int main() {
const std::string s = min_(std::string("A"), std::string("B"));
fprintf(stderr, "min: %s/n", s.c_str());
return 0;
}
Como observación interesante, en mi máquina clang++ -O3
genera 54 instrucciones para el código anterior frente a 62 instrucciones para el std::min
. Sin embargo, con -O0
genera 518 instrucciones para el código anterior frente a 481 para el -O0
std::min
.
Beta_ab&&
Beta::toAB() const {
return move(Beta_ab(1, 1));
}
Esto devuelve una referencia colgante, al igual que con el caso de referencia lvalue. Después de que la función retorna, el objeto temporal será destruido. Debería devolver Beta_ab
por valor, como el siguiente
Beta_ab
Beta::toAB() const {
return Beta_ab(1, 1);
}
Ahora, está moviendo correctamente un objeto Beta_ab
temporal en el valor de retorno de la función. Si el compilador puede, evitará el movimiento por completo, mediante el uso de RVO (optimización del valor de retorno). Ahora, puedes hacer lo siguiente
Beta_ab ab = others.toAB();
Y moverá construir el temporal en ab
, o hacer RVO para omitir hacer un movimiento o copiar por completo. Le recomiendo que lea BoostCon09 Rvalue References 101 que explica el asunto y cómo (N) RVO interactúa con esto.
Su caso de devolver una referencia de valor sería una buena idea en otras ocasiones. Imagine que tiene una función getAB()
que a menudo invoca temporalmente. No es óptimo hacer que devuelva una referencia de const lvalue para valores temporales rvalue. Puedes implementarlo así
struct Beta {
Beta_ab ab;
Beta_ab const& getAB() const& { return ab; }
Beta_ab && getAB() && { return move(ab); }
};
Tenga en cuenta que move
en este caso no es opcional, porque ab
no es un valor local automático ni un valor r temporal. Ahora, el calificador de ref &&
dice que la segunda función se invoca en rvalue temporales, haciendo el siguiente movimiento, en lugar de copiar
Beta_ab ab = Beta().getAB();