inicialização de referência em C ++
-
19-09-2019 - |
Pergunta
Greetings, todos!
Examinando meu próprio código, eu vim a esta linha interessante:
const CString &refStr = ( CheckCondition() ) ? _T("foo") : _T("bar");
Agora estou completamente perdido, e não consegue entender por que ela é legal. Tanto quanto eu compreender, const referência deve ser inicializada, quer com o valor de r ou l-valor. referências não inicializadas não pode existir. Mas ()? operador executa uma função CheckCondition () antes de ele atribui valor para a referência. Eu posso ver agora que, enquanto CheckCondition () é executado, refStr existe, mas ainda não inicializado. O que acontecerá se CheckCondition () irá lançar uma exceção, ou passar o controle com uma instrução goto? Será que vai deixar a referência inicializada ou estou faltando alguma coisa?
Solução
exemplo mais simples: const int x = foo();
Esta constante também tem de ser inicializado, e para isso foo()
precisa ser chamado. O que acontece no fim necessário:. X entra em existência apenas quando foo retorna
Para responder às suas perguntas adicionais: Se foo()
seria throw
, a exceção será capturado por um algum lugar catch()
. O bloco try{}
para que catch()
rodeado const int x = foo();
obviamente. Daí const int x
está fora do escopo já, e é irrelevante que nunca tem um valor. E se não há nenhuma catch
para a exceção, o seu programa (incluindo const int x
) está desaparecido.
C ++ não tem aleatório goto
de. Eles podem saltar dentro foo()
mas isso não importa; foo()
ainda tem de voltar.
Outras dicas
Está faltando alguma coisa - é totalmente código legal, e na verdade esse código é um dos usos mais comuns e melhores do operador condicional. É sempre um erro pensar que o compilador deve fazer internamente as coisas na mesma ordem que o código é Definiu na página - é perfeitamente livre para avaliar o operador condicional (que é Justv outra expressão) e, em seguida, utilizar o resultado para executar a inicialização.
Quanto a um goto, não há nenhuma maneira de usar um em uma inicialização. E se uma exceção é lançada, a referência é considerado nunca ter sido criado em primeiro lugar.
referências não inicializadas não pode existir.
Infelizmente coisas engraçadas pode ser feito durante a inicialização. Você também poderia ter escrito
const int& a = foobar(a) ? 1 : 2;
ou para o assunto
const int& a = a;
suponho como o compilador procede da esquerda para a direita, um é de fato no âmbito do lado direito, então tecnicamente , você deve ser capaz de usá-lo e na melhor das hipóteses ele pode avisar:
"ComeauTest.c", a linha 9: warning: variável "a" é usado antes seu valor é definido
const int& a = foobar(a) ? 1 : 2;
^
Naturalmente, isso só pode resultar em um comportamento indefinido como com o uso de qualquer variável não inicializada.
O seu exemplo é bom, desde que você não usar a referência antes de ter sido inicializado.
Eu posso ver agora que, enquanto CheckCondition () é executado, refStr existe, mas ainda não inicializado.
Do ponto advogado de vista da linguagem, isso é errado. Durante a inicialização, refStr
ainda não existe. Eu acho que o depurador visual é dando-lhe enganosa dicas.
Se o código dentro das pistas de inicialização para uma condição de erro, refStr
não vai existir, e não irá nunca ter existido.
Esta é completamente legal. Ou este for concluído com êxito e a referência é vinculado a um objeto válido ou uma exceção é lançada e controle é transferido fora do bloco ea referência não está no escopo de modo cuidados Noone de mais.
Uma exceção levará para um lugar onde refStr não é acessível e você não pode ir para um lugar onde ele é de lá. A Goto não será capaz de sair da CheckCondition () se for uma função, e você não será capaz de usar um goto se é uma macro. A longjmp () terá o mesmo efeito que uma exceção:. Você vai para um lugar onde refStr não é acessível