2010-08-04 15 views
19

Acabo de tener un comportamiento extraño de una versión de g ++ para Windows que obtuve con Strawberry Perl. Me permitió omitir una declaración de devolución.Omitir declaración de devolución en C++

que tienen una función miembro que devuelve una estructura que consta de dos punteros, llamado boundTag:

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

Esta función me dio una mala salida, y descubrí que no tenía ninguna instrucción de retorno. Tuve la intención de devolver retBoundTag pero olvidé escribir la declaración de devolución. Una vez que agregué return retBoundTag; todo estaba bien.

Pero probé esta función y obtuve la salida correcta de boundTag. Incluso ahora, cuando elimino la declaración de devolución, g ++ la compila sin previo aviso. WTF? ¿Adivina devolver retBoundTag?

+5

Debe compilar usando '-Wall'. Las declaraciones de devolución faltantes son capturadas por '-Wreturn-type'. – jweyrich

+0

Tiendo a convertir la advertencia sobre un retorno faltante en un error con: '-Werror = return-type'. Me ahorro mucho tiempo. –

Respuesta

16

La omisión de la declaración return en una función non-void [Salvo main()] y utilizando el valor devuelto en su código invoca Undefined Behaviour.

ISO C++ - 98 [Sección 6.6.3/2]

Una instrucción de retorno con una expresión puede usarse sólo en funciones que devuelven un valor; el valor de la expresión es devuelto a la persona que llama de la función. Si es necesario, la expresión se convierte implícitamente al tipo de retorno de la función en la que aparece . Una declaración de devolución puede implicar la construcción y copia de un objeto temporal (class.temporary). Salir del final de una función es equivalente a una devolución sin valor; esto da como resultado comportamiento indefinido en una función de devolución de valor.

Por ejemplo

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 
} 

Generalmente g ++ da una warning: control reaches end of non-void function. Intente compilar con la opción -Wall.

+7

Omitir la declaración de devolución está bien. La ejecución que llega al final de una función sin encontrar una declaración de retorno produce un comportamiento indefinido. Puede regresar antes de llegar al final de la función, o dejarla lanzando una excepción, o simplemente no abandonarla, y todo estaría bien definido. –

+0

¿por qué usar 'p' es peligroso? – ajay

+2

@ajay: Eso es porque no contiene ningún valor especificado. –

12

C y C++ no requieren que tenga una declaración return. Puede que no sea necesario tener uno, porque la función entra en un bucle infinito o porque arroja una excepción.

Prasoon ya citado la parte relevante de la norma:

[Sección 6.6.3/2]

Una instrucción de retorno con una expresión sólo se puede utilizar en funciones que devuelven un valor; el valor de la expresión se devuelve a la persona que llama de la función. Si es necesario, la expresión se convierte implícitamente al tipo de devolución de la función en la que aparece. Una declaración de devolución puede involucrar la construcción y copia de un objeto temporal (class.temporary). Fluir fuera del final de una función es equivalente a un retorno sin valor; esto da como resultado un comportamiento indefinido en una función que devuelve valor.

Lo que significa es que no tener una instrucción de retorno está bien. Pero llegando al final de la función sin devolver es comportamiento indefinido.

El compilador no siempre puede detectar estos casos, así que no es necesario para ser un error de compilación (que tendría que resolver el problema de la parada para determinar si la ejecución vez realmente llega al final de la función). Es simplemente undefined lo que debería suceder si esto ocurre. Puede parecer que funciona (porque la función de llamada simplemente verá el valor de basura en la ubicación donde se supone que debe estar el valor de retorno), podría colapsar o hacer que los demonios salgan volando.

+3

Gracias por explicar por qué no es un error de compilación no tener una declaración de devolución explícita en non-void funciones :) – ajay

2

A pesar de que el compilador aC++ no puede siempre detectar cuando una función no puede ejecutar una instrucción de retorno, que por lo general lata.

Por el lado positivo, al menos g ++ hace que esto sea fácil de detectar con la opción del compilador de línea de comandos "-Wreturn-type". Solo necesita recordar habilitarlo. (También se habilita si usa "-Wall").

Cuestiones relacionadas