¿Está bien devolver el valor del argumento predeterminado por referencia constante como en los ejemplos a continuación:
https://coliru.stacked-crooked.com/a/ff76e060a007723b
#include <string>
const std::string& foo(const std::string& s = std::string(""))
{
return s;
}
int main()
{
const std::string& s1 = foo();
std::string s2 = foo();
const std::string& s3 = foo("s");
std::string s4 = foo("s");
}
c++
language-lawyer
object-lifetime
default-arguments
reference-binding
Corazón congelado
fuente
fuente

std::stringcon una clase propia para que pueda rastrear la construcción y la destrucción.Respuestas:
En su código, ambos
s1ys3son referencias colgantes.s2ys4están bienEn la primera llamada, el
std::stringobjeto vacío temporal creado a partir del argumento predeterminado se creará en el contexto de la expresión que contiene la llamada. Por lo tanto, morirá al final de la definición des1, lo que dejas1colgando.En la segunda llamada, el
std::stringobjeto temporal se usa para inicializars2, luego muere.En la tercera llamada, el literal de cadena
"s"se usa para crear unstd::stringobjeto temporal y que también muere al final de la definición des3, dejandos3colgando.En la cuarta llamada, el
std::stringobjeto temporal con valor"s"se usa para inicializars4y luego muere.Ver C ++ 17 [class.temporary] /6.1
fuente
No es seguro :
fuente
std::string s2 = foo();es válido (después de todo, no se pasa ninguna referencia explícitamente)?Depende de lo que hagas con la cuerda después.
Si su pregunta es ¿ es correcto mi código? entonces sí lo es.
De [dcl.fct.default] / 2
Entonces su código es efectivamente equivalente a:
Todo su código es correcto, pero no hay extensión de duración de referencia en ninguno de estos casos, ya que el tipo de retorno es una referencia.
Como llama a una función con un carácter temporal, la vida útil de la cadena devuelta no extenderá la instrucción.
Su ejemplo con
s2está bien ya que copia (o mueve) desde el temporal antes del final del satement.s3tiene el mismo problema ques1.fuente