Li que literais de string têm duração de armazenamento estática, isso significa que referências a elas são sempre válidas? Por exemplo, o código a seguir é seguro:
std::function<void()> foo(const std::string& name){
// capture name by reference
return [&](){
std::cout<<"The name is "<<name<<std::endl;
};
}
int main() {
std::function<void()> func;
{
func = foo("test");
func(); // func called in the same scope
}
func(); // func called in the outer scope
}
E se, em vez disso, primeiro criássemos uma string a partir desse literal de string e referenciássemos isso:
std::function<void()> foo(const std::string& name){
// capture name by reference
return [&](){
std::cout<<"The name is "<<name<<std::endl;
};
}
int main() {
std::function<void()> func;
{
std::string test = "test";
func = foo(test);
func(); // func called in the same scope
}
func(); // func called in the outer scope
}
Não, isso não é seguro.
name
não é uma referência a uma string literal. Strings literais não sãostd::string
objetos, então umstd::string
objeto temporário, sem nome object é construído ename
é uma referência a esse objeto. Seu lambda então captura uma referência a esse mesmo objeto temporário.O tempo de vida desses objetos temporários termina no final da expressão completa na qual eles são criados, então o tempo de vida desse objeto termina após a
func = foo("test");
expressão. Se você chamarfunc
depois desse ponto, você acessará o objeto temporário após seu tempo de vida ter terminado, o que resulta em comportamento indefinido.O comportamento do seu segundo programa também é indefinido. Seu lambda mantém uma referência a
test
, e o tempo de vida desse objeto termina no fim do seu escopo envolvente. Chamarfunc
depois desse ponto significa acessartest
depois que seu tempo de vida terminou, levando a um comportamento indefinido.Literais de string não são
std::string
objetos. Eles são arrays simples dechar
s. Ou seja, o tipo de"test"
échar[5]
. Esse array tem duração de armazenamento estático. Se você fosse capturar uma referência a esse array, então você estaria seguro; ou seja, o seguinte é bem definido: