¿Por qué asignar un valor de retorno a una referencia?

5 minutos de lectura

Estoy revisando un código y todas las llamadas a una función que devuelve una cadena se asignan a una referencia. El prototipo de función algo así como:

 std::string GetPath(const std::string& top);

y se usa como

std::string& f = GetPath(cw);

o

 const std::string& f = GetPath(cw);

¿Por qué se usaría una referencia aquí en lugar de

 std::string f = GetPath(cw);

  • No es un duplicado en absoluto en realidad. Simplemente ambos implican referencias. Si eso hace un duplicado, entonces la mitad de las preguntas de C ++ sobre SO deberían cerrarse (que de hecho puede ser el caso, pero por otras razones).

    – Edward Extraño

    13 de enero de 2011 a las 20:09

  • Te recomiendo aclarar: ¿Preguntas también por funciones que no solo devuelven valores pero también referencias?

    – Johannes Schaub – litb

    14 de enero de 2011 a las 11:22

  • Posible duplicado del valor de retorno de la tienda de la función en la referencia C++

    – bobobobo

    3 de noviembre de 2021 a las 15:04


  • También relacionado: referencia de rvalue y valor de retorno de una función

    – bobobobo

    3 de noviembre de 2021 a las 15:10

Avatar de usuario de CB Bailey
CB Bailey

Si la función devolvió una referencia (que no lo hace) entonces es posible que desee asignar el valor de retorno a una referencia para mantenerse “al día” con cualquier cambio en ese objeto. La referencia devuelta tendría que ser a un objeto con una duración que se extendiera más allá del final de la función.

O (si la referencia devuelta no era-const) porque quería mantener una referencia al objeto para mutarlo como un punto posterior. (Si quisiera mutarlo inmediatamente, lo haría directamente, sin necesidad de almacenar la referencia).

Como la función devuelve un valor, puede asignarlo a un const referencia (a un no-const la referencia sería ilegal) y extender la vida útil del objeto a la vida útil de la referencia. Sin embargo, el efecto sería exactamente el mismo (const aparte) como almacenar el valor en un objeto directamente.

Cualquier pensamiento de que podría ser menos eficiente puede resultar infundado y puede calificar el objeto con const si tu tambien quieres (La mayoría de los compiladores eliminan el temporal implícito y construyen el valor de retorno en el objeto que se inicializa).

Como el tipo de objeto se devuelve desde la función por valor, debe ser copiable, por lo que no es razón para usar una referencia debido a la preocupación de que no lo sea.

  • ¡Guau, y ni siquiera tuviste que agregar insultos sin fundamento!

    – GManNickG

    13 de enero de 2011 a las 20:39

  • Podría estar mostrándome como un anciano (¿quién sabía?), pero la última vez que miré, vincular temporales a referencias constantes fue un truco de optimización bueno y barato que solo se compartió celosamente. Puedo ver que la semántica de movimiento lo hará bastante inútil, pero ¿qué pasó con C++03 que hizo que esto fuera “equivocado”?

    – sbi

    13 de enero de 2011 a las 21:21


  • Si se hubiera conocido al autor del código, lo anterior sería bastante insultante. Retrata al autor del código como “equivocado” y con “miedo”. Y creer eso sobre el autor, no ayuda al OP. Por el contrario, decir que el autor del código es incompetente o estúpido es simplemente una evaluación. Ayuda al OP sabiendo que no debe confiar en que hay buenas razones para el resto del código.

    – Saludos y hth. – alf

    13 de enero de 2011 a las 21:26

  • @Alf: “equivocado” no es un insulto. Simplemente significa “actuar en el error”. Todos cometemos errores, esto no es nada nuevo. Por el contrario, “estúpido” e “incompetente” reciben un trato diferente porque se utilizan para degradar y desmoralizar a una persona, sin mencionar que están actuando por error. Y “miedo” tampoco es un insulto. Simplemente significa “cauteloso”, “preocupado” o “cuidadoso”; ¿No debemos tener cuidado? No, la diferencia entre las respuestas es casual y la lectura no maliciosa de esta respuesta no produce insultos, mientras que la tuya los presenta en primer plano.

    – GManNickG

    13 de enero de 2011 a las 21:42


  • @Alf: Además, sbi ha demostrado que cree que este tipo de código vale la pena. ¿Por qué no lo llamas estúpido o incompetente directamente con él? ¿Solo le haces eso a la gente que no puede responder? Muy maduro.

    – GManNickG

    13 de enero de 2011 a las 21:43

Esta es probablemente una optimización demasiado entusiasta dirigida a los casos en que la función que se llama devuelve una referencia, como en:

const std::string& func();
...
const std::string& tmp = func();
...

para guardar en la copia de cadena.

  • Esta respuesta sería mejor si notara lo inútil que es hacer tal cosa, pero sí, probablemente haya precisado los motivos.

    – Edward Extraño

    13 de enero de 2011 a las 23:07

  • Hmm, no creo que esto sea completamente inútil. Creo que hay casos extremos en los que quizás quieras hacer esto en C++98.

    – Nikolái Fetissov

    14 de enero de 2011 a las 2:54


avatar de usuario de Peanut
maní

Ok, es completamente inútil. Y se ve horrible. Y no válido c ++. Justo no hazlo.

Editar: para una mejor comprensión de lo que quiero decir

reference & var = funcNotReturningReference(); //invalid C++
const reference & cvar = funcNotReturningReference(); //silly C++, no saving costs (reference to temporary stops temporary from being released, but this code does not help anything)

  • Apuesto a que obtienes +20 por eso. Prestigio.

    – Edward Extraño

    13 de enero de 2011 a las 20:13

  • -1. const std::string& result = function(); es perfectamente válido C++.

    – Carreras de ligereza en órbita

    13 de enero de 2011 a las 20:16

  • Siempre es mejor razonar que insultar.

    – maní

    13 de enero de 2011 a las 20:18

  • @peenut: Estoy de acuerdo. Desafortunadamente, su razonamiento es erróneo. 🙂

    – Carreras de ligereza en órbita

    13 de enero de 2011 a las 20:23

  • @peenut Todavía tiene fallas. struct Foo { std::string str; Foo() : str("Long string here") {} }; Foo f; Foo& bar() { return f; } /* ... */ const Foo& ref = bar(); puede muy bien darle ahorros de costos. Si usa un objeto muy complejo en lugar de un std::stringentonces los costos de ahorro podría ser significativo No digo que siempre lo serán, solo que podrían serlo. Todo este “esto siempre es inútil y estúpido” que flota en torno a esta pregunta no tiene fundamento y es una forma triste de generalizar lo que en realidad es un tema bastante complejo.

    – Carreras de ligereza en órbita

    14 de enero de 2011 a las 11:06


¿Ha sido útil esta solución?