Respuestas:
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 regrese, el objeto temporal se destruirá. Debe devolver Beta_ab
por valor, como el siguiente
Beta_ab
Beta::toAB() const {
return Beta_ab(1, 1);
}
Ahora, está moviendo correctamente un Beta_ab
objeto temporal al valor de retorno de la función. Si el compilador puede, evitará el movimiento por completo, utilizando RVO (optimización del valor de retorno). Ahora puedes hacer lo siguiente
Beta_ab ab = others.toAB();
Y se moverá a construir lo temporal ab
, o hará RVO para omitir hacer un movimiento o copiar por completo. Le recomiendo leer 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 getAB()
función que a menudo invoca de forma temporal. No es óptimo hacer que devuelva una referencia constante de valor para los valores temporales de valor. Puedes implementarlo así
struct Beta {
Beta_ab ab;
Beta_ab const& getAB() const& { return ab; }
Beta_ab && getAB() && { return move(ab); }
};
Tenga move
en cuenta que en este caso no es opcional, ya ab
que no es un valor local automático ni temporal. Ahora, el calificador de referencia &&
dice que la segunda función se invoca en los valores temporales de valor, haciendo el siguiente movimiento, en lugar de copiar
Beta_ab ab = Beta().getAB();
Se puede ser más eficiente, por ejemplo, en un contexto diferente bits:
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 versus 62 instrucciones para el código regular std::min
. Sin embargo, con -O0
esto genera 518 instrucciones para el código anterior versus 481 para el código regular std::min
.
for(:)
e integración sobre objeto desasignado. Solución: ideone.com/tQVOal
std::move()
solo se usa como un reparto explícito para ilustrar el punto más claramente. No es un código que copiarías y pegarías en tu proyecto. No contradice la respuesta más votada, porque se crea un objeto temporal dentro de la función. Aquí el objeto devuelto es uno de los argumentos (los objetos temporales se destruyen como el último paso para evaluar la expresión completa que (léxicamente) contiene el punto donde fueron creados).