¿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::string
con una clase propia para que pueda rastrear la construcción y la destrucción.Respuestas:
En su código, ambos
s1
ys3
son referencias colgantes.s2
ys4
están bienEn la primera llamada, el
std::string
objeto 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 dejas1
colgando.En la segunda llamada, el
std::string
objeto temporal se usa para inicializars2
, luego muere.En la tercera llamada, el literal de cadena
"s"
se usa para crear unstd::string
objeto temporal y que también muere al final de la definición des3
, dejandos3
colgando.En la cuarta llamada, el
std::string
objeto temporal con valor"s"
se usa para inicializars4
y 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
s2
está bien ya que copia (o mueve) desde el temporal antes del final del satement.s3
tiene el mismo problema ques1
.fuente