2010-08-01 24 views
50

descubrí que el siguiente código es aceptado por Visual C++ 2008 y GCC 4.3 compiladores:¿Está devolviendo el código válido?

void foo() 
{ 

} 

void bar() 
{ 
    return foo(); 
} 

Estoy un poco sorprendido de que compila. ¿Es esta una característica del lenguaje o es un error en los compiladores? ¿Qué dicen los estándares de C/C++ sobre esto?

Respuesta

66

Es una característica del lenguaje de C++

C++ (ISO 14882: 2003) 6.6.3/3

Una instrucción de retorno con una expresión de tipo “vacío cv” sólo se puede utilizar en las funciones con un tipo de devolución de vacío cv; la expresión se evalúa justo antes de que la función regrese a su llamador.

C (ISO 9899: 1999) 6.8.6.4/1

Una instrucción de retorno con una expresión no debe aparecer en una función cuyo tipo de retorno es nula.

+1

Tenga en cuenta que muchos compiladores que pueden compilar ambos C y C++ ofrecerán el C++ regla como una extensión no estándar durante la compilación de código en C, aunque esto no debe ser invocado si quieres ser portátil. –

49

sí, es un código válido. Esto es necesario cuando tiene funciones de plantilla para que pueda usar un código uniforme. Por ejemplo,

template<typename T, typename P> 
T f(int x, P y) 
{ 
    return g(x, y); 
} 

Ahora, g puede estar sobrecargada para volver vacío cuando el segundo argumento es un tipo particular. Si "return void" no es válido, la llamada al f se romperá.

+1

'T' no puede ser nulo, porque un parámetro no puede ser nulo. – strager

+0

Gracias, me he dado cuenta unos minutos después de que he dado un mal ejemplo. ¡Fijo! – zvrba

+3

Esta característica también abre una pequeña trampa: en 'void positive_action (int n) {if (n <0) return; acción (n); [...]} ', si' action' devuelve void, entonces olvidando el punto y coma después de 'return' no dará errores o advertencias, pero' action' ahora se llama cuando whe'n' es negativo en vez de cuando es positivo. –

5

Esto es válido y puede ser muy útil por ejemplo para crear un código más limpio en situaciones cuando se quiere hacer un poco de control de errores antes de regresar:

void ErrRet(int code, char* msg) 
{ 
    // code logging/handling error 
} 
void f() 
{ 
    if (...) return ErrRet(5, "Error Message !"); 
    // code continue 
} 
1

Válido hecho. Yo lo uso a menudo para las macros de validación de entrada:

#define ASSERT_AND_RETURN_IF_NULL(p,r) if (!p) { assert(p && "#p must not be null"); return r; } 

bool func1(void* p) { 
    ASSERT_AND_RETURN_IF_NULL(p, false); 
    ... 
} 

void func2(void* p) { 
    ASSERT_AND_RETURN_IF_NULL(p, void()); 
    ... 
} 
Cuestiones relacionadas