2010-08-01 4 views
50

Je trouve que le code suivant est accepté par Visual C++ 2008 et GCC 4.3 compilateurs:Est-ce que le code valide est invalide?

void foo() 
{ 

} 

void bar() 
{ 
    return foo(); 
} 

Je suis un peu surpris qu'il compile. Est-ce une fonctionnalité de langue ou est-ce un bug dans les compilateurs? Que disent les normes C/C++ à ce propos?

Répondre

66

Il est une fonctionnalité de langage C++

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

Une déclaration de retour avec une expression de type « vide cv » peut être utilisé que dans les fonctions avec un type de retour de cv vide; l'expression est évaluée juste avant que la fonction ne retourne à son appelant.

C (ISO 9899: 1999) 6.8.6.4/1

Une déclaration de retour avec une expression ne doit pas apparaître dans une fonction dont le type de retour est vide.

+1

Notez que de nombreux compilateurs qui peuvent compiler à la fois C et C++ offrent la règle C++ comme une extension non standard lors de la compilation du code C, bien que cela ne devrait pas être invoqué si vous voulez être portable. –

49

Oui, c'est un code valide. Ceci est nécessaire lorsque vous avez des fonctions de modèle afin que vous puissiez utiliser un code uniforme. Par exemple,

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

Maintenant, g pourrait être surchargée pour revenir vide lorsque le second argument est un type particulier. Si "return void" était invalide, l'appel à f serait alors rompu.

+1

'T' ne peut pas être annulé, car un paramètre ne peut pas être annulé. – strager

+0

Merci, je me suis rendu compte quelques minutes après que j'ai donné un mauvais exemple. Fixé! – zvrba

+3

Cette fonctionnalité ouvre aussi un petit piège: dans void positive_action (int n) {if (n <0) return; action (n); [...]} ', si' action' renvoie void, alors oublier le point-virgule apr'es 'return' ne donnera pas d'erreur ou d'avertissement, mais' action' sera maintenant appelé whe 'n' est négatif plutôt que positif. –

5

Ceci est valable et peut être très utile par exemple pour créer un code plus propre dans des situations où vous voulez faire une gestion des erreurs avant de retourner:

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

Valid effet. Je l'utilise souvent pour les macros de validation d'entrée:

#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()); 
    ... 
} 
Questions connexes