118 votes

Lorsque l'on utilise des en-têtes C en C++, doit-on utiliser des fonctions de std: : ou de l'espace de noms global ?

Le C est en quelque sorte, mais pas exactement, un sous-ensemble du C++. Nous pouvons donc utiliser la plupart des fonctions/en-têtes C en C++ en changeant légèrement le nom ( stdio.h a cstdio , stdlib.h a cstdlib ).

Ma question est en fait plutôt sémantique. Dans un code C++ (utilisant la dernière version du compilateur GCC), je peux appeler printf("Hello world!"); y 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 sous la forme suivante std::printf("Hello world!"); .

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

0 votes

Je doute qu'il y ait une différence. Il semble que printf() soit simplement inclus dans la fonction std mais d'après la description faite par cppreference, il nécessite toujours l'utilisation de cstdio . Il suffit de tenir compte des espaces de noms (ou de leur absence).

18 votes

Si un jour ils rendent obligatoire la mise en décharge des C dans l'espace de noms global est illégale, je préfère utiliser la méthode de l'espace de noms global. std:: qualifie les versions. (D'ailleurs, j'aurais préféré qu'ils les rendent illégales).

3 votes

@Galik : D'accord. Ce serait

110voto

sergej Points 1749

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

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

  1. Pour la compatibilité avec la bibliothèque standard C ...
  2. Chaque en-tête C, dont le nom est de la forme nom.h se comporte comme si chaque nom placé dans t par l'espace de noms de la bibliothèque standard nom est placé dans l'en-tête espace de noms global champ d'application. Il est non spécifié si ces noms sont d'abord déclarés ou définis à l'intérieur de l'espace de noms (3.3.6) de l'espace nominatif std et sont ensuite injectés dans l'espace de noms global par des déclarations d'utilisation explicites (7.3.3).
  3. Ejemplo: L'en-tête <cstdlib> assurément fournit ses déclarations et définitions à l'intérieur des dénominationspa 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 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épréciée, ils ont été identifiés comme candidats à la suppression dans les révisions futures.

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

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

En d'autres termes : préférer

#include <cstdio>

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

plus

#include <stdio.h>

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

1 votes

La norme N3242 n'est pas une norme C++. N3337 est le projet qui présente le moins de différences avec C++11.

3 votes

Voir également l'article de Jonathan Wakely Pourquoi < cstdlib > est plus compliqué que vous ne le pensez des blogs de Red Hat. Il détaille un certain nombre de problèmes du point de vue de l'implémentation de la bibliothèque standard C++. Il fournit également un historique remontant à C++98.

0 votes

@sergej - Connaîtriez-vous par hasard le traitement de C++03 sur le sujet ? Ou est-ce que c'est au hasard ce qui va se passer ?

82voto

T.C. Points 22510

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

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

Utilisez la forme garantie par l'en-tête que vous incluez.

7 votes

Le STL mal déguisé ?

0 votes

@nwp non (15 chars)

1 votes

@T.C. Malheureusement, lorsque j'ai essayé sur mon compilateur, ni l'un ni l'autre ne s'est avéré efficace. <cmeow> ni <meow.h> ne prévoit ni ::std::purr ni ::purr mais plutôt une erreur de pré-processeur. Seulement <cstdio> y/o <stdio.h> fournit ::std::printf y/o ::printf . :P

9voto

jalf Points 142628

Non, vous êtes bien dans les deux cas.

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

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

En fait, vous pouvez utiliser ce que vous préférez. Le plus courant est probablement d'utiliser les fonctions de la 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'une comme "meilleure" que l'autre.

2 votes

"Et il n'y a pas de consensus clair sur le fait que l'utilisation des versions std: : est "la bonne chose à faire"." Euh, oui, il y a absolument un consensus sur le fait que c'est la bonne chose à faire.

4 votes

Comment déterminer objectivement si un consensus a été atteint ou non ?

10 votes

@JeremyFriesner vous en parlez sur SO et vous verrez si vous avez des commentaires divergents :)

3voto

REACHUS Points 971

La seule différence est qu'en std::printf() en ajoutant std:: vous vous protégez contre l'écriture future d'une fonction portant le même nom, ce qui entraînerait un conflit d'espace de noms. Les deux utilisations conduiront exactement aux mêmes appels à l'API du système d'exploitation (vous pouvez le vérifier sous Linux en exécutant la commande strace your_program ).

Je trouve qu'il est très improbable que quelqu'un nomme une fonction de cette manière, comme printf() est l'une des fonctions les plus utilisées. En outre, en C++, iostream sont préférés aux appels à cstdio comme printf.

1 votes

Au contraire, je trouve cela très probable : printf est cruellement défectueux en C++ en raison de son manque de typage fort, le remplacer par une meilleure version est tout à fait naturel.

1 votes

@KonradRudolph Vous pouvez le trouver comme ça si vous voulez, mais vous auriez tort ; il n'est pas conçu pour avoir un typage fort, et il y a beaucoup de problèmes qui ne peuvent pas être résolus avec le typage fort requis facilement. C'est pourquoi de nombreuses solutions comparables en C++ sont beaucoup plus lentes que printf. Si vous voulez le remplacer par une "meilleure" version, vous rompez le contrat entre le langage et le programmeur, et vous êtes en état de péché pour commencer.

1 votes

@Alice Uhm, je ne romps aucun contrat : std::printf est différent de mynamespace::printf et le C++ me permet explicitement de définir mes propres fonctions dont les noms imitent ceux des fonctions à l'intérieur de std . Ce n'est tout simplement pas discutable. Quant à vos affirmations selon lesquelles printf est efficace en raison d'un typage lâche, c'est bien sûr également faux. printf n'est même pas particulièrement efficace, il existe de nombreuses implémentations plus efficaces qui sont fortement typées.

3voto

NeonMercury Points 41

Extrait de la norme C++11 :

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

Ainsi, si vous utilisez <cstdio> vous pouvez être sûr que printf sera dans la namespace std et n'est 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 méthode C++.

C'est pourquoi j'utilise <cstdio> et vous conseillent de le faire.

4 votes

J'aimerais que cela fonctionne ainsi, mais ce n'est pas le cas. Si vous incluez <cstdio> vous avez la garantie que std::printf existera, mais il y a une aucune garantie de la norme if ::printf existera ou n'existera pas non plus. En fait, dans tous les compilateurs que j'ai entendus parler de ::printf es injecté dans l'espace de noms global lorsque vous incluez <cstdio> .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X