Omissão de declaração de retorno em C ++

Acabei de ter algum comportamento estranho de uma versão do g + + para Windows que obtive com o Strawberry Perl. Isso me permitiu omitir uma declaração de retorno.

Eu tenho uma function de membro que retorna uma estrutura composta por dois pointers, chamado boundTag :

 struct boundTag Box::getBound(int side) { struct boundTag retBoundTag; retBoundTag.box = this; switch (side) { // set retBoundTag.bound based on value of "side" } } 

Essa function me deu uma saída ruim e descobri que ela não tinha instrução de retorno. Eu pretendia retornar retBoundTag mas esqueci de escrever a declaração de retorno. Uma vez que eu adicionei return retBoundTag; tudo estava bem.

Mas eu testei essa function e boundTag saída boundTag correta dela. Mesmo agora, quando eu removo a declaração de retorno, g + + a compila sem avisar. WTF Adivinha para retornar retBoundTag ?

Omitir a declaração de return em uma function non-void [Exceto main() ] e usar o valor retornado em seu código invoca o comportamento indefinido .

ISO C ++ – 98 [Seção 6.6.3 / 2]

Uma instrução de retorno com uma expressão pode ser usada apenas em funções que retornam um valor; o valor da expressão é retornado ao chamador da function. Se necessário, a expressão é implicitamente convertida no tipo de retorno da function em que aparece. Uma declaração de retorno pode envolver a construção e a cópia de um object temporário ( class.temporary ). Fluir do final de uma function é equivalente a um retorno sem valor; isso resulta em comportamento indefinido em uma function de retorno de valor .

Por exemplo

 int func() { int a=10; //do something with 'a' //oops no return statement } int main() { int p=func(); //using p is dangerous now //return statement is optional here } 

Geralmente, o g ++ dá um warning: control reaches end of non-void function . Tente compilar com a opção -Wall .

C e C ++ não exigem que você tenha uma declaração de return . Pode não ser necessário ter um, porque a function entra em um loop infinito ou porque gera uma exceção.

A Prasoon já citou a parte relevante da norma:

[Seção 6.6.3 / 2]

Uma instrução de retorno com uma expressão pode ser usada apenas em funções que retornam um valor; o valor da expressão é retornado ao chamador da function. Se necessário, a expressão é implicitamente convertida no tipo de retorno da function em que aparece. Uma declaração de retorno pode envolver a construção e a cópia de um object temporário (class.temporary). Fluir do final de uma function é equivalente a um retorno sem valor; isso resulta em comportamento indefinido em uma function de retorno de valor.

O que significa é que não ter uma declaração de retorno é ok. Mas chegar ao final da function sem retornar é um comportamento indefinido .

O compilador nem sempre pode detectar esses casos, portanto, não é necessário que seja um erro de compilation (ele teria que resolver o problema de parada para determinar se a execução realmente atinge o final da function). É simplesmente indefinido o que deve acontecer se isso ocorrer. Pode parecer que funciona (porque a function de chamada irá apenas olhar para qualquer valor de lixo que esteja no local onde o valor de retorno deveria estar), ele pode falhar ou fazer demônios voarem para fora do seu nariz.

Mesmo que o compilador aC ++ não possa sempre detectar quando uma function não pode executar uma instrução de retorno, ela geralmente pode.

No lado positivo, pelo menos g + + torna isso fácil de detectar com a opção de compilador de linha de comando “-Wreturn-type”. Você só precisa se lembrar de ativá-lo. (Também é ativado se você usar “-Wall”.)