2010-07-06 18 views
7

Bien, pequeña rareza que descubrí con mi compilador de C++.¿Implica C++ declaraciones de devolución?

Tenía un código no demasiado complejo para refactorizar, y accidentalmente me las arreglé para dejar en una ruta que no tenía una declaración de devolución. Mi error. Por otro lado, esto compilado, y segfaulted cuando lo ejecuté y ese camino fue golpeado, obviamente.

Aquí está mi pregunta: ¿Es esto un error del compilador, o no hay garantía de que un compilador de C++ imponga la necesidad de una declaración de devolución en una función de devolución no válida?

Ah, y para ser claros, en este caso era una declaración innecesaria si no acompañaba a los demás. Sin gotos, sin salidas, sin abortos.

+0

¿Qué compilador estás usando? – Dennis

+3

Si está en gcc use ['-Wreturn-type'] (http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html), posiblemente con' -Werror = '. –

+0

me pasó lo mismo con gcc 4.4 –

Respuesta

11

Personalmente creo que esto debe ser un error:

int f() { 
} 

int main() { 
    int n = f(); 
    return 0; 
} 

pero la mayoría de los compiladores tratan como una advertencia, y usted puede incluso tener que usar modificadores del compilador para obtener esa advertencia.Por ejemplo, en g ++ necesita -Wall para obtener:

[[email protected] NeilB]$ g++ -Wall nr.cpp 
nr.cpp: In function 'int f()': 
nr.cpp:2: warning: no return statement in function returning non-void 

Por supuesto, con g ++ siempre se debe compilar con al menos -Wall de todos modos.

13

No hay garantía de que un compilador de C++ haga cumplir eso. Una función de C++ podría salirse de su flujo de control por mecanismos desconocidos para el compilador. El contexto cambia cuando se usa C++ para escribir un núcleo del sistema operativo es un ejemplo de eso. Una excepción no detectada lanzada por una función llamada (cuyo código no está necesariamente disponible para la persona que llama) es otra.

Algunos otros lenguajes, como Java, imponen explícitamente que con el conocimiento disponible en tiempo de compilación, todas las rutas devuelven un valor. En C++ esto no es cierto, como ocurre con muchas otras ocasiones en el lenguaje, como tampoco se marca el acceso a una matriz fuera de sus límites.

+0

"Una función C++ podría salirse de su flujo de control por mecanismos desconocidos para el compilador". - Sí, pero el flujo será devuelto a. Después de todo, un interruptor de contexto cambia de nuevo. Realmente no veo qué tiene que ver esto con los valores devueltos. El único caso en el que no se revertirá la función es si se lanza una excepción. –

+0

@Neil no es necesario. Una llamada a 'exit', por ejemplo, nunca saltará. –

+1

@Johannes OK, y abortar() y terminar(). Pero el compilador no puede ver que estos niegan la necesidad de un retorno, a menos que los trate como "especiales" de alguna manera. –

4

El compilador no hace cumplir esto porque usted tiene conocimiento sobre qué rutas son prácticamente posibles que el compilador no tiene. El compilador normalmente solo conoce ese archivo en particular, no otros que pueden afectar el flujo dentro de una función determinada. Entonces, no es un error.

En Visual Studio, sin embargo, es una advertencia. Y debemos prestar atención a todas las advertencias ... ¿verdad? :)

Editar: Parece haber alguna discusión sobre cuándo podría suceder esto. Aquí hay un ejemplo modificado pero real de mi biblioteca personal de códigos;

enum TriBool { Yes, No, Maybe }; 

TriBool GetResult(int input) { 
    if (TestOne(input)) { 
     return Yes; 
    } else if (TestTwo(input)) { 
     return No; 
    } 
} 

Ten en cuenta que este es el código anterior. Originalmente hubo un "retorno de otro tipo tal vez" allí. :) Si TestOne y TestTwo están en una unidad de compilación diferente, cuando el compilador acierta con este código, no puede decir si TestOne y TestTwo pueden devolver false para una entrada determinada. Usted, como programador que escribió TestOne y TestTwo, sabe que si TestOne falla, TestTwo tendrá éxito. Tal vez haya efectos secundarios de esas pruebas, así que tienen que hacerse. ¿Sería mejor escribirlo sin el "else if"? Tal vez. Probablemente. Pero el punto es que esto es legal C++ y el compilador no puede saber si es posible salir sin una declaración de devolución. Es, estoy de acuerdo, feo y no es una buena codificación, pero es legal y Visual Studio te dará una advertencia, pero se compilará.

Recuerde que C++ no se trata de protegerlo de usted mismo. Se trata de permitirte hacer lo que tu corazón desea dentro de las limitaciones del lenguaje, incluso si eso incluye dispararse en el pie.

+0

Esto no tiene sentido. El compilador debe tener conocimiento de qué rutas son posibles para compilar el código. –

+1

@Neil creo que tiene un punto. El compilador no siempre sabe en * compile time *. Como si no tuviese ni idea cuando publicaste tu comentario que publicaría una respuesta. Pero ahora usted sabe, y posiblemente tenga precauciones para responder a su vez, o no. O estás totalmente sorprendido, como lo será el C++, y haces cosas indefinidas :) –

+1

Eso no tiene sentido en mi humilde opinión. El gráfico de flujo de control de cualquier función dada es perfectamente conocido por el compilador después de analizar su código. Es posible que algunos bordes nunca se crucen mientras se ejecuta el código (piense en afirmaciones), pero el compilador lo trata como tal y todo lo que causa es solo una suposición (excesivamente) conservadora. – jpalecek

Cuestiones relacionadas