web-dev-qa-db-fra.com

Lorsque vous utilisez des en-têtes C en C ++, devons-nous utiliser des fonctions de std :: ou de l'espace de noms global?

C est un peu, pas exactement, un sous-ensemble de C++. Nous pouvons donc utiliser la plupart des fonctions/en-têtes C en C++ en changeant un peu le nom (stdio.h En cstdio, stdlib.h En cstdlib).

Ma question est en fait un peu sémantique. Dans le code C++ (en utilisant la dernière version du compilateur GCC), je peux appeler printf("Hello world!"); et std::printf("Hello world!"); et cela fonctionne exactement de la même manière. Et dans la référence que j'utilise, il apparaît également comme std::printf("Hello world!");.

Ma question est, est-il préférable d'utiliser std::printf(); en C++? Y a-t-il une différence?

104
DeiDei

De la norme C++ 11 (c'est moi qui souligne):

en-têtes de bibliothèque standard D.5 C [en-têtes depr.c.]

  1. Pour la compatibilité avec la bibliothèque standard C ...
  2. Chaque en-tête C, dont chacun a un nom de la forme name.h, se comporte comme si chaque nom placé dans l'espace de noms de bibliothèque standard par l'en-tête cname correspondant était placé dans la portée espace de noms global. Il est non spécifié si ces noms sont d'abord déclarés ou définis dans la portée de l'espace de noms (3.3.6) sur l'espace de noms std puis injectés dans le portée globale de l'espace de noms par des déclarations d'utilisation explicites (7.3.3).
  3. Exemple: L'en-tête <cstdlib>assurément fournit ses déclarations et définitions dans l'espace de noms std. Il peut également fournir ces noms dans l'espace de noms global. L'en-tête <stdlib.h>assurément fournit les mêmes déclarations et définitions dans l'espace de noms global, un peu comme dans la norme C. Il peut également fournir ces noms dans l'espace de noms std.

L'utilisation des en-têtes "name.h" est déconseillée, ils ont été identifiés comme candidats à la suppression des futures révisions.

Je suggère donc d'inclure les en-têtes "cname" et d'utiliser les déclarations et définitions de l'espace de noms std.

Si vous devez utiliser les en-têtes "name.h" pour certaines raisons (c'est obsolète, voir ci-dessus), je suggère d'utiliser les déclarations et définitions de l'espace de noms global.

En d'autres termes: préférez

#include <cstdio>

int main() {
    std::printf("Hello world\n");
}

plus de

#include <stdio.h>

int main() {
    printf("Hello world\n");
}
100
sergej

<cmeow> fournit toujours ::std::purr et peut ou non fournir ::purr.

<meow.h> fournit toujours ::purr et peut ou non fournir ::std::purr.

Utilisez le formulaire garanti par l'en-tête que vous incluez.

78
T.C.

Non, tu vas bien de toute façon.

L'intention originale était que le <___.h> les en-têtes seraient les versions C qui mettent tout dans l'espace de noms global, et les <c___> les en-têtes seraient les versions ified C++, qui placent tout dans l'espace de noms std.

En pratique, cependant, les versions C++ également mettent tout dans l'espace de noms global. Et il n'y a pas de consensus clair sur l'utilisation de std:: versions est "la bonne chose à faire".

Donc, en gros, utilisez celui que vous préférez. La plus courante consiste probablement à utiliser les fonctions de bibliothèque standard C dans l'espace de noms global (printf au lieu de std::printf), mais il n'y a pas beaucoup de raisons de considérer l'un comme "meilleur" que l'autre.

7
jalf

De ma propre pratique: utilisez std:: préfixes. Sinon, un jour abswill vous mordra très douloureusement au cas où vous utilisez des points flottants.

abs non qualifié fait référence à une fonction définie sur int sur certaines plates-formes. Sur d'autres, il est surchargé. Toutefois std::abs est toujours surchargé pour tous les types.

3
eiennohito

La seule différence est que dans std::printf() en ajoutant la résolution de portée std::, Vous vous protégerez de quelqu'un écrivant une fonction avec le même nom à l'avenir, ce qui conduirait à un conflit d'espace de noms. Les deux utilisations conduiront exactement aux mêmes appels d'API OS (vous pouvez le vérifier sous Linux en exécutant strace your_program).

Je trouve très peu probable que quelqu'un nomme une fonction comme ça, car printf() est l'une des fonctions les plus couramment utilisées. De plus, en C++, iostreams sont préférables aux appels aux fonctions cstdio comme printf.

3
syntagma

De la norme C++ 11:

Chaque en-tête C, dont chacun a un nom de la forme name.h, se comporte comme si chaque nom placé dans l'espace de noms de bibliothèque standard par l'en-tête cname correspondant est placé dans la portée de l'espace de noms global. Il n'est pas précisé si ces noms sont d'abord déclarés ou définis dans la portée de l'espace de noms (3.3.6) de l'espace de noms std, puis injectés dans la portée de l'espace de noms global par des déclarations explicites d'utilisation (7.3.3).

Donc, si vous utilisez <cstdio>, vous pouvez être sûr que printf sera dans le namespace std, et donc pas dans l'espace de noms global.
L'utilisation d'un espace de noms global crée un conflit de noms. Ce n'est pas la manière C++.

Par conséquent, j'utilise <cstdio> en-têtes et vous conseille de le faire.

3
NeonMercury

In stdio

Il s'agit de la version C++ de l'en-tête de la bibliothèque C standard @c stdio.h, et son contenu est (principalement) le même que cet en-tête, mais est tous contenu dans l'espace de noms @c std (à l'exception des noms définis comme macros dans C).

Cela ne devrait donc faire aucune différence.

2
anukul

Utiliser simplement printf sans std:: pourrait générer des conflits de noms et est considéré comme une mauvaise pratique par de nombreux développeurs c ++. Google est votre ami sur celui-ci, mais voici quelques liens, j'espère que cela vous aidera

Pourquoi "utiliser l'espace de noms std" est-il considéré comme une mauvaise pratique?http://www.cplusplus.com/forum/beginner/61121/

2
razvan