2010-08-01 11 views
50

Ich fand heraus, dass der folgende Code von Visual C++ 2008 und GCC 4.3 Compiler akzeptiert wird:Gibt ungültigen gültigen Code zurück?

void foo() 
{ 

} 

void bar() 
{ 
    return foo(); 
} 

überrascht Ich bin ein bisschen, dass es kompiliert. Ist das eine Sprachfunktion oder ist es ein Fehler in den Compilern? Was sagen die C/C++ - Standards dazu?

Antwort

66

Es ist eine Sprache-Funktion von C++

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

Eine return-Anweisung mit einem Ausdruck des Typs „cv Leere“ in Funktionen nur verwendet werden können, mit einem Rückgabetyp von cv void; Der Ausdruck wird ausgewertet, kurz bevor die Funktion zu ihrem Aufrufer zurückkehrt.

C (ISO 9899: 1999) 6.8.6.4/1

Eine return-Anweisung mit einem Ausdruck darf nicht in einer Funktion erscheinen, deren Rückgabetyp ist nichtig.

+1

Beachten Sie, dass viele Compiler, die kompilieren kann sowohl C und C++ wird die C++ Regel als Nicht-Standard-Erweiterung bieten, während C-Code kompiliert, obwohl dies nicht geltend gemacht werden sollte wenn du tragbar sein willst. –

49

Ja, es ist ein gültiger Code. Dies ist erforderlich, wenn Sie über Vorlagenfunktionen verfügen, sodass Sie einheitlichen Code verwenden können. Zum Beispiel

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

Nun g könnte überlastet werden Leere zurück, wenn das zweite Argument einige besondere Art ist. Wenn "Rückgabe ungültig" ungültig wäre, würde der Aufruf an f dann brechen.

+1

'T' kann nicht ungültig sein, weil ein Parameter nicht ungültig sein kann. – strager

+0

Danke, ich habe mich ein paar Minuten später erkannt, dass ich ein schlechtes Beispiel gegeben habe. Fest! – zvrba

+3

Diese Funktion öffnet auch eine kleine Falle: in 'Leere positive_action (int n) {wenn (n <0) zurück; Aktion (n); [...]} ', wenn' action' void zurückgibt, dann vergisst das Semikolon nach 'return' keine Fehler oder Warnungen, aber' action' wird jetzt aufgerufen, wenn 'n' negativ ist und nicht wenn es positiv ist. –

5

Dieses gültig und kann sehr nützlich sein, zum Beispiel saubereren Code in Situationen zu erstellen, wenn Sie vor der Rückkehr einig Fehlerbehandlung zu tun:

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

tatsächlich gültig. Ich benutze es oft für Eingabevalidierung Makros:

#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()); 
    ... 
} 
Verwandte Themen