Tudo bem retornar o valor do argumento padrão por referência const, como nos exemplos abaixo:
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
Coração congelado
fonte
fonte
std::string
por uma classe própria para poder acompanhar a construção e a destruição.Respostas:
No seu código, ambos
s1
es3
são referências pendentes.s2
es4
estão bem.Na primeira chamada, o
std::string
objeto vazio temporário criado a partir do argumento padrão será criado no contexto da expressão que contém a chamada. Portanto, ele morrerá no final da definição des1
, o que deixas1
pendente.Na segunda chamada, o
std::string
objeto temporário é usado para inicializars2
e depois morre.Na terceira chamada, a string literal
"s"
é usada para criar umstd::string
objeto temporário e que também morre no final da definição des3
, deixandos3
dangling.Na quarta chamada, o
std::string
objeto temporário com valor"s"
é usado para inicializars4
e depois morre.Veja C ++ 17 [class.temporary] /6.1
fonte
Não é seguro :
fonte
std::string s2 = foo();
é válido (afinal, nenhuma referência é passada explicitamente)?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
Portanto, seu código é efetivamente equivalente a:
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.
Seu exemplo com
s2
é bom, já que você copia (ou move) do temporário antes do final do processo.s3
tem o mesmo problema ques1
.fonte