Depende do que você faz com a sequência posteriormente.
Se sua pergunta for, meu código está correto? então sim é isso.
De [dcl.fct.default] / 2
[ Exemplo : a declaração
void point(int = 3, int = 4);
declara uma função que pode ser chamada com zero, um ou dois argumentos do tipo int. Pode ser chamado de qualquer uma das seguintes maneiras:
point(1,2); point(1); point();
As duas últimas chamadas são equivalentes a point(1,4)
e point(3,4)
, respectivamente. - exemplo final ]
Portanto, seu código é efetivamente equivalente a:
const std::string& s1 = foo(std::string(""));
std::string s2 = foo(std::string(""));
Todo o seu código está correto, mas não há extensão de vida útil de referência em nenhum desses casos, pois o tipo de retorno é uma referência.
Como você chama uma função com um temporário, a vida útil da string retornada não prolongará a instrução.
const std::string& s1 = foo(std::string("")); // okay
s1; // not okay, s1 is dead. s1 is the temporary.
Seu exemplo com s2
é bom, já que você copia (ou move) do temporário antes do final do processo. s3
tem o mesmo problema que s1
.
std::string
por uma classe própria para poder acompanhar a construção e a destruição.