Voltando const referência a variável local a partir de uma função
-
13-09-2019 - |
Pergunta
Eu tenho algumas perguntas sobre retornar uma referência a uma variável local de uma função:
class A {
public:
A(int xx)
: x(xx)
{
printf("A::A()\n");
}
};
const A& getA1()
{
A a(5);
return a;
}
A& getA2()
{
A a(5);
return a;
}
A getA3()
{
A a(5);
return a;
}
int main()
{
const A& newA1 = getA1(); //1
A& newA2 = getA2(); //2
A& newA3 = getA3(); //3
}
As minhas perguntas são =>
-
é a implementação de
getA1()
correto? Eu sinto que é incorreta, pois é devolver o endereço de uma variável local ou temporário. -
Qual das afirmações em
main
(1,2,3) vai levar a um comportamento indefinido? -
Em
const A& newA1 = getA1();
faz a garantia padrão que uma temporária ligada por uma referência const não será destruído até que a referência fica fora do escopo?
Solução
1. implementação
getA1()
é correto? Eu sinto que é incorreto como ele está retornando endereço da variável local ou temporária.
A única versão do getAx()
que está correto em seu programa é getA3()
. Ambos os outros têm um comportamento indefinido, não importa como você usá-los mais tarde.
2. Qual das afirmações em principal (1,2,3) vai levar a um comportamento indefinido?
Em uma nenhum sentido deles. Para 1 e 2 o comportamento indefinido é como um resultado dos corpos das funções. Para a última linha, newA3
deve ser um erro de compilação que você não pode vincular um temporário para uma referência não const.
3. Em
const A& newA1 = getA1();
faz garantias padrão que encadernados temporária por umconst
referência não será destruído até que a referência fica fora do escopo?
No. O seguinte é um exemplo de que:
A const & newConstA3 = getA3 ();
Aqui, getA3()
retorna uma temporária e o tempo de vida que temporária está agora ligado ao objeto newConstA3
. Em outras palavras, o temporária existirá até newConstA3
sai do escopo.
Outras dicas
Q1:. Sim, este é um problema, ver resposta à Q2
Q2: 1 e 2 são indefinido como eles se referem a variáveis ??locais na pilha de getA1 e getA2. Essas variáveis ??ir fora do escopo e não estão mais disponíveis e pior pode ser substituído como a pilha está em constante mutação. getA3 trabalha desde uma cópia do valor de retorno é criado e retornado ao chamador.
Q3:. Sem tal garantia existe para ver a resposta para Q2
Eu acho que o principal problema é que você não está voltando temporários em tudo, você deve
return A(5);
em vez de
A a(5);
return a;
Caso contrário, você está retornando endereço da variável local, não temporário. E o temporário para referência const só funciona para temporários.
Eu acho que é explicado aqui: temporária para const referência
Se você vai compilar isso em VC6 você vai receber este aviso
****** aviso do compilador (nível 1) C4172 retornando endereço do variável local ou temporária Uma função retorna o endereço de uma variável local ou objecto temporário. As variáveis ??locais e objetos temporários são destruídos quando uma função retorna, assim que o endereço retornado não é válido. ******
Ao testar para este problema que eu encontrei coisa interessante (determinado código está trabalhando em VC6):
class MyClass
{
public:
MyClass()
{
objID=++cntr;
}
MyClass& myFunc()
{
MyClass obj;
return obj;
}
int objID;
static int cntr;
};
int MyClass::cntr;
main()
{
MyClass tseadf;
cout<<(tseadf.myFunc()).objID<<endl;
}