c++ - ¿Está bien devolver el valor del argumento predeterminado por referencia constante?
language-lawyer object-lifetime (3)
Depende de lo que hagas con la cuerda después.
Si su pregunta es ¿ es correcto mi código? entonces sí lo es.
[ Ejemplo : la declaración
void point(int = 3, int = 4);
declara una función que se puede llamar con cero, uno o dos argumentos de tipo int. Se puede llamar de cualquiera de estas formas:
point(1,2); point(1); point();
Las dos últimas llamadas son equivalentes al
point(1,4)
y alpoint(3,4)
, respectivamente. - ejemplo final ]
Entonces su código es efectivamente equivalente a:
const std::string& s1 = foo(std::string(""));
std::string s2 = foo(std::string(""));
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.
const std::string& s1 = foo(std::string("")); // okay
s1; // not okay, s1 is dead. s1 is the temporary.
Su ejemplo con
s2
está bien ya que copia (o mueve) desde el temporal antes del final del satement.
s3
tiene el mismo problema que
s1
.
¿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");
}
En su código, tanto
s1
como
s3
son referencias colgantes.
s2
y
s4
están bien.
En la primera llamada, el objeto
std::string
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 de
s1
, lo que deja a
s1
colgando.
En la segunda llamada, el objeto temporal
std::string
se usa para inicializar
s2
, luego muere.
En la tercera llamada, el literal de cadena
"s"
se usa para crear un objeto temporal
std::string
y que también muere al final de la definición de
s3
, dejando
s3
colgando.
En la cuarta llamada, el objeto temporal
std::string
con el valor
"s"
se usa para inicializar
s4
y luego muere.
Ver C ++ 17 [class.temporary] /6.1
Un objeto temporal vinculado a un parámetro de referencia en una llamada de función (8.2.2) persiste hasta la finalización de la expresión completa que contiene la llamada.
No es seguro :
En general, la vida útil de un temporal no puede extenderse aún más "pasándola": una segunda referencia, inicializada a partir de la referencia a la que estaba vinculado el temporal, no afecta su vida útil.