Pourquoi l'utilisation de "namespace std" est-elle considérée comme une mauvaise pratique?
d'autres m'ont dit qu'écrire using namespace std
en code est une erreur, et que je devrais utiliser std::cout
et std::cin
directement à la place.
pourquoi using namespace std
est-il considéré comme une mauvaise pratique? Est-il inefficace ou risque-t-il de déclarer des variables ambiguës (variables qui partagent le même nom qu'une fonction dans std
namespace)? Cela a-t-il un impact sur la performance?
30 réponses
cela n'a rien à voir avec la performance. Mais considérez ceci: vous utilisez deux bibliothèques appelées Foo et Bar:
using namespace foo;
using namespace bar;
Tout fonctionne très bien, vous pouvez appeler Blah()
de Foo et Quux()
de Bar sans problèmes. Mais un jour, vous mettez à jour vers une nouvelle version de Foo 2.0, qui offre maintenant une fonction appelée Quux()
. Maintenant, vous avez un conflit: à la fois Foo 2.0 et la barre d'importation Quux()
dans votre espace de noms global. Cela va prendre un certain effort pour corriger, surtout si les paramètres de la fonction correspondent.
si vous aviez utilisé foo::Blah()
et bar::Quux()
, alors l'introduction de foo::Quux()
aurait été un non-événement.
Je suis d'accord avec tout Greg a écrit , mais je voudrais ajouter: il peut même être pire que Greg a dit!
Bibliothèque Foo 2.0 pourrait introduire une fonction, Quux()
, qui est une correspondance sans ambiguïté meilleure pour certains de vos appels à Quux()
que le bar::Quux()
votre code a appelé pendant des années. Alors votre code compile toujours , mais il appelle silencieusement la mauvaise fonction et ne Dieu-sait-quoi. C'est à peu près aussi mauvais que les choses peuvent devenir.
gardez à l'esprit que l'espace de noms std
a des tonnes d'identificateurs, dont beaucoup sont très communs (penser list
, sort
, string
, iterator
, etc.) qui sont très susceptibles à apparaître dans d'autres, trop.
si vous considérez ceci peu probable: il y avait une question posée ici sur le débordement de la pile où à peu près exactement cela s'est produit (mauvaise fonction appelée en raison de l'omission du préfixe std::
) environ six mois après que j'ai donné cette réponse. ici est un autre exemple plus récent d'une telle question.
C'est donc un réel problème.
" voici un point de données de plus: il y a de nombreuses années, j'avais aussi l'habitude de trouver ennuyeux d'avoir à préfixe tout à partir de la bibliothèque standard avec std::
. Puis j'ai travaillé dans un projet où il a été décidé au départ que les deux directives using
et les déclarations sont interdites sauf pour les portées de fonction. Devinez quoi? Il a fallu à la plupart d'entre nous très peu de semaines pour s'habituer à l'écriture du préfixe, et après quelques semaines de plus, la plupart d'entre nous ont même convenu que cela rendait le code plus lisible . Il y a une raison à cela: si vous aimez la prose plus courte ou plus longue est subjective, mais les préfixes ajoutent objectivement de la clarté au code. non seulement le compilateur, mais vous aussi, trouvez plus facile de voir à quel identifiant il est fait référence.
en une décennie, ce projet a connu une croissance de plusieurs millions de lignes de code. Puisque ces discussions reviennent encore et encore, j'ai été curieux une fois de savoir combien de fois la fonction-portée using
(autorisée) a été utilisée dans le projet. Je grep avais les sources pour elle et trouvé seulement une ou deux douzaines d'endroits où il a été utilisé. Pour moi, cela indique que, une fois essayé, les développeurs ne trouvent pas std::
assez douloureux à employer en utilisant des directives, même une fois tous les 100 kLoC même où il a été autorisé à être utilisé.
conclusion: préfixer explicitement tout ne fait pas de mal, prend très peu de s'habituer, et a des avantages objectifs. En particulier, elle rend le code plus facile à interpréter par le compilateur et par les lecteurs humains - et cela devrait probablement être le but principal lors de l'écriture de code.
je pense que c'est dommage de le mettre dans les fichiers d'en-tête de vos classes: car alors vous seriez obliger toute personne qui veut utiliser vos classes (y compris les fichiers d'en-tête) "à l'aide" (voir tout) d'autres espaces de noms.
cependant, vous pouvez vous sentir libre de mettre une déclaration d'utilisation dans votre (privé) *.fichiers cpp.
méfiez-vous que certaines personnes sont en désaccord avec mon dire" feel free " comme ceci -- parce que bien qu'un énoncé d'utilisation dans un fichier cpp soit meilleur que dans un en-tête (parce qu'il n'affecte pas les personnes qui incluent votre fichier d'en-tête), ils pensent qu'il n'est toujours pas bon (parce que selon le code, il pourrait rendre la mise en œuvre de la classe plus difficile à maintenir). Cette FAQ, rubrique dit,
la directive using existe pour le code C++ et pour faciliter la transition vers namespaces, mais vous ne devriez probablement pas l'utiliser sur une base régulière, du moins pas dans votre nouveau code C++.
il suggère deux alternatives:
-
a utilisant la déclaration:
using std::cout; // a using-declaration lets you use cout without qualification cout << "Values:";
-
passez outre et tapez std::
std::cout << "Values:";
j'ai récemment rencontré une plainte au sujet de Visual Studio 2010 . Il s'est avéré que presque tous les fichiers source a ces deux lignes:
using namespace std;
using namespace boost;
beaucoup de Boost des fonctionnalités vont dans le standard C++0x, et Visual Studio 2010 a beaucoup de fonctionnalités C++0x, donc soudainement ces programmes ne compilaient pas.
par conséquent, éviter using namespace X;
est une forme de future-proofing, un moyen de s'assurer qu'un changement dans les bibliothèques et/ou les fichiers d'en-tête utilisés ne va pas casser un programme.
version courte: n'utilisez pas global en utilisant des déclarations ou des directives dans les fichiers d'en-tête. N'hésitez pas à utiliser dans les fichiers de mise en œuvre. Voici ce Que Herb Sutter et Andrei Alexandrescu ont à dire sur cette question dans C++ Coding Standards (bolding for emphasis is mine):
résumé
espace de Noms de l'usage, pour votre commodité, et non pour vous infligent à d'autres: ne Jamais écrire une déclaration using ou une utiliser la directive avant une directive # include.
corollaire: dans les fichiers d'en-tête, n'écrivez pas le niveau namespace en utilisant des directives ou des déclarations; au lieu de cela, nommespace explicitement-qualifiez tous les noms. (La deuxième règle découle de la première, parce que les en-têtes ne peuvent jamais savoir quel autre #d'en-tête inclut pourrait apparaître après eux.)
Discussion
en bref: vous pouvez et devez utiliser namespace en utilisant des déclarations et des directives libéralement dans vos fichiers de mise en œuvre après #include directives et se sentir bien à ce sujet. malgré les affirmations répétées du contraire, namespace en utilisant des déclarations et des directives n'est pas mauvais et ils ne vont pas à l'encontre du but des namespaces. Ils sont plutôt ce qui rend les espaces de noms utilisables .
on ne devrait pas utiliser la directive à portée globale, surtout dans les en-têtes. Toutefois, il existe des situations où cela est approprié même dans un fichier d'en-tête:
template <typename FloatType> inline
FloatType compute_something(FloatType x)
{
using namespace std; //no problem since scope is limited
return exp(x) * (sin(x) - cos(x * 2) + sin(x * 3) - cos(x * 4));
}
c'est mieux qu'une qualification explicite ( std::sin
, std::cos
)...)
parce qu'il est plus court et a la capacité de travailler avec les types de point flottants définis par l'utilisateur (via la recherche dépendante de L'Argument).
ne pas utiliser à l'échelle mondiale
il est considéré comme" mauvais "seulement lorsque utilisé globalement . Parce que:
- vous encombrez l'espace de noms que vous programmez.
- les lecteurs auront de la difficulté à voir d'où vient un identifiant particulier, quand vous utilisez beaucoup de
using namespace xyz
. - Tout ce qui est vrai pour autre les lecteurs de votre code source est encore plus vrai pour les plus fréquentes lecteur de: vous-même. Revenez dans un an ou deux et jetez un oeil...
- si vous ne parlez que de
using namespace std
vous pourriez ne pas être au courant de tous les trucs que vous attrapez -- et quand vous ajoutez un autre#include
ou passez à une nouvelle révision C++ vous pourriez avoir des conflits de noms dont vous n'étiez pas au courant.
vous pouvez l'utiliser localement
allez-y et utilisez-le localement (presque) librement. Ce, de bien sûr, vous empêche de répéter std::
-- et la répétition est aussi mauvaise.
Un idiome pour l'utiliser localement
en C++03, Il y avait un idiom -- code boilerplate -- pour implémenter une fonction swap
pour vos classes. Il a été suggéré que vous utilisiez en fait un using namespace std
local -- ou au moins using std::swap
:
class Thing {
int value_;
Child child_;
public:
// ...
friend void swap(Thing &a, Thing &b);
};
void swap(Thing &a, Thing &b) {
using namespace std; // make `std::swap` available
// swap all members
swap(a.value_, b.value_); // `std::stwap(int, int)`
swap(a.child_, b.child_); // `swap(Child&,Child&)` or `std::swap(...)`
}
Cela fait la magie suivante:
- le le compilateur choisira
std::swap
pourvalue_
, i.e.void std::swap(int, int)
. - si vous avez une surcharge
void swap(Child&, Child&)
implémentée, le compilateur le choisira. - Si vous n' pas ont qui surcharge le compilateur utilisera
void std::swap(Child&,Child&)
et essayer de son mieux la permutation de ces.
avec C++11 Il n'y a plus de raison d'utiliser ce modèle. La mise en œuvre de std::swap
a été changée en trouver une surcharge et le choisir.
si vous importez les fichiers d'en-tête de droite vous avez soudainement des noms comme hex
, left
, plus
ou count
dans votre champ d'Application global. Ce pourrait être surprenant si vous n'êtes pas au courant que std::
contient ces noms. Si vous essayez également d'utiliser ces noms localement, cela peut conduire à une certaine confusion.
si tout le matériel standard est en son propre namespace vous n'avez pas à vous soucier des collisions de noms avec votre code ou d'autres bibliothèques.
les programmeurs expérimentés utilisent tout ce qui résout leurs problèmes et évitent tout ce qui crée de nouveaux problèmes, et ils évitent les directives d'en-tête-niveau de fichier en utilisant-pour cette raison précise.
programmeurs expérimentés essaient également d'éviter la qualification complète des noms à l'intérieur de leurs fichiers source. Une raison mineure pour cela est qu'il n'est pas élégant d'écrire plus de code quand moins de code est suffisant à moins qu'il n'y ait de bonnes raisons . L'une des principales raisons pour cela est désactiver l'argument-recherche dépendante (ADL).
que sont ces bonnes raisons ? Parfois les programmeurs veulent explicitement désactiver ADL, d'autres fois ils veulent désambiguer.
donc les suivants sont OK:
- Fonction-niveau directives à l'aide et à l'aide de déclarations à l'intérieur des fonctions de mise en œuvre,
- de la Source au niveau des fichiers à l'aide de déclarations à l'intérieur des fichiers source
- (Parfois) à la source au niveau des fichiers à l'aide de directives
je suis d'accord qu'il ne devrait pas être utilisé globalement, mais ce n'est pas si mal d'utiliser localement, comme dans un namespace
. Voici un exemple de "le langage de programmation C++" :
namespace My_lib {
using namespace His_lib; // everything from His_lib
using namespace Her_lib; // everything from Her_lib
using His_lib::String; // resolve potential clash in favor of His_lib
using Her_lib::Vector; // resolve potential clash in favor of Her_lib
}
dans cet exemple, nous avons résolu les conflits de noms potentiels et les ambiguïtés découlant de leur composition.
Les Noms qui y sont explicitement déclarés (y compris les noms qui y sont déclarés par l'utilisation-des déclarations comme His_lib::String
) ont priorité sur noms rendus accessibles dans un autre domaine par une directive d'utilisation ( using namespace Her_lib
).
une autre raison est la surprise.
si je vois cout << blah
, au lieu de std::cout << blah
je pense qu'est-ce que c'est cout
? Est-ce le normal cout
? Est-il quelque chose de spécial?
je considère aussi que c'est une mauvaise pratique. Pourquoi? Un jour, j'ai pensé que la fonction d'un namespace était de diviser les choses pour que je ne les gâche pas en les jetant dans un sac global.
Cependant, si j'utilise souvent 'cout' et' cin', j'écris: using std::cout; using std::cin;
dans le fichier cpp (jamais dans le fichier d'en-tête car il se propage avec #include
). Je pense que personne de sain d'esprit ne nommera jamais un ruisseau cout
ou cin
. ;)
C'est agréable de voir le code et de savoir ce qu'il fait. Si je vois std::cout
, je sais que c'est le flux cout
de la bibliothèque std
. Si je vois cout
alors je ne sais pas. pourrait être cout
le ruisseau de la std
de la bibliothèque. Ou il pourrait y avoir une int cout = 0;
dix lignes plus haut dans la même fonction. Ou une variable static
nommée cout
dans ce fichier. Il pourrait être n'importe quoi.
prenez maintenant un million la base de code de ligne, qui n'est pas particulièrement grande, et vous cherchez un bug, ce qui signifie que vous savez qu'il y a une ligne dans ce million de lignes qui ne fait pas ce qu'elle est censée faire. cout << 1;
pourrait lire un static int
nommé cout
, vers la gauche d'un bit, et de jeter le résultat. Je cherche un insecte, je dois vérifier ça. Vous voyez comme je préfère voir std::cout
?
C'est une de ces choses qui semblent vraiment une bonne idée si vous êtes un enseignant et n'avez jamais eu à écrire et à maintenir un code pour gagner votre vie. J'aime voir le code où (1) je sais ce qu'il fait; et, (2) je suis convaincu que la personne qui écrit ce qu'il savait ce qu'il fait.
il s'agit de gérer la complexité. Utiliser l'espace de noms va tirer des choses que vous ne voulez pas, et donc peut-être le rendre plus difficile à déboguer (je dis peut-être). Utiliser std:: partout est plus difficile à lire (plus de texte et tout ça).
chevaux pour les cours-gérer votre complexité comment vous pouvez le mieux et se sentir capable.
-
vous devez être capable de lire le code écrit par des gens qui ont des opinions différentes sur le style et les meilleures pratiques que vous.
-
si vous n'utilisez que cout, personne ne se trompe. Mais quand vous avez beaucoup d'espaces de noms qui volent autour et vous voyez cette classe et vous n'êtes pas exactement sûr de ce qu'elle fait, avoir l'espace de noms explicite agit comme un commentaire de sortes. Vous pouvez voir à première vue, "oh, c'est une opération du système de fichiers" ou "c'est de faire d'autres choses réseau'.
utiliser plusieurs espaces de noms en même temps est évidemment une recette pour le désastre, mais utiliser juste l'espace de noms std
et seulement l'espace de noms std
n'est pas si grand d'une affaire à mon avis parce que la redéfinition ne peut se produire par votre propre code...
il suffit donc de considérer ces fonctions comme des noms réservés comme" int "ou" classe " et c'est tout.
les gens devraient arrêter d'être si anal à ce sujet. Ton prof avait raison depuis le début. Il suffit d'utiliser UNE espace de noms; c'est tout l'intérêt de l'utilisation des espaces de noms la première place. Vous n'êtes pas censé utiliser plusieurs en même temps. Sauf si c'est votre propre. Encore une fois, la redéfinition ne se produira pas.
prendre en considération
// myHeader.h
#include <sstream>
using namespace std;
// someoneElses.cpp/h
#include "myHeader.h"
class stringstream { // uh oh
};
notez que c'est un exemple simple, si vous avez des fichiers avec 20 includes et d'autres importations, vous aurez une tonne de dépendances à passer pour comprendre le problème. Le pire à ce sujet est que vous pouvez obtenir des erreurs sans rapport dans d'autres modules en fonction des définitions qui entrent en conflit.
ce n'est pas horrible, mais vous vous éviterez des maux de tête en ne l'utilisant pas dans les fichiers d'en-tête ou l'espace de noms global. C'est probablement d'accord pour le faire dans des portées très limitées, mais je n'ai jamais eu de problème à taper les 5 caractères supplémentaires pour clarifier d'où viennent mes fonctions.
un namespace est une portée nommée. Les espaces de noms sont utilisés pour grouper les déclarations liées et pour garder séparé les éléments séparés. Par exemple, deux bibliothèques développées séparément peuvent utiliser le même nom pour désigner différentes les éléments, mais un utilisateur peut toujours utiliser les deux:
namespace Mylib{
template<class T> class Stack{ /* ... */ };
/ / ...
}
namespace Yourlib{
class Stack{ /* ... */ };
/ / ...
}
void f(int max) {
Mylib: :Stack<int> s1(max) ; / / use my stack
Yourlib: :Stack s2(max) ; / / use your stack
/ / ...
}
répéter un nom d'espace de noms peut être une distraction pour les lecteurs et les écrivains. Par conséquent, il est possible pour indiquer que les noms d'un espace de noms particulier sont disponibles sans être explicites qualification. Par exemple:
void f(int max) {
using namespace Mylib; / / make names from Mylib accessible
Stack<int> s1(max) ; / / use my stack
Yourlib: :Stack s2(max) ; / / use your stack
/ / ...
}
Namespaces fournir un outil puissant pour la gestion des différentes bibliothèques et des différentes versions de code. En particulier, ils offrent le programmeur alternatives de façon explicite pour faire référence à un nonlocal nom.
Source: un aperçu du langage de programmation C++ par Bjarne Stroustrup
exemple concret pour clarifier la préoccupation. Imaginez que vous ayez une situation où vous avez 2 bibliothèques, foo et bar, chacune avec leur propre espace de noms:
namespace foo {
void a(float) { /* does something */ }
}
namespace bar {
...
}
Maintenant, disons que vous utilisez foo et bar ensemble dans votre propre programme comme suit:
using namespace foo;
using namespace bar;
void main() {
a(42);
}
à ce stade, tout va bien. Lorsque vous exécutez votre programme de "quelque chose". Mais plus tard, vous mettez à jour la barre et disons qu'il a changé pour être comme:
namespace bar {
void a(float) { /* does something completely different */ }
}
à ce point vous obtiendrez une erreur de compilateur:
using namespace foo;
using namespace bar;
void main() {
a(42); // error: call to 'a' is ambiguous, should be foo::a(42)
}
donc vous aurez besoin de faire de la maintenance pour clarifier quel" a "vous vouliez dire (i.e. foo::a
). C'est probablement indésirable, mais heureusement c'est assez facile (il suffit d'ajouter foo::
devant tous les appels à a
que le compilateur marque comme ambigu).
mais imaginez un scénario alternatif où bar a changé à la place de ressembler à ceci à la place:
namespace bar {
void a(int) { /* does something completely different */ }
}
à ce point votre appel à a(42)
se lie soudainement à bar::a
au lieu de foo::a
et au lieu de faire" quelque chose "il fait" quelque chose de complètement différent". Pas d'avertissement de compilateur ou quoi que ce soit. Votre programme commence silencieusement à faire quelque chose de complètement différent qu'avant.
quand vous utilisez un namespace vous risquez un scénario comme celui-ci, c'est pourquoi les gens sont mal à l'aise en utilisant des namespaces. Le plus de choses dans un namespace, plus le risque de conflit est grand, de sorte que les gens pourraient être encore plus inconfortables à utiliser namespace std (en raison du nombre de choses dans cet namespace) que d'autres namespaces.
en fin de compte, il s'agit d'un compromis entre la possibilité d'écriture et la fiabilité/maintenabilité. La lisibilité peut aussi jouer un rôle, mais je vois des arguments pour que cela aille dans un sens ou dans l'autre. Normalement, je dirais que la fiabilité et la maintenabilité sont plus importantes, mais dans ce cas, vous paierez constamment le coût d'écriture pour un impact de fiabilité/maintenabilité assez rare. Le "meilleur" compromis déterminera votre projet et vos priorités.
exemple où l'utilisation de std namespace provoque une erreur de complilation à cause de l'ambiguïté du nombre, qui est aussi une fonction dans la bibliothèque d'algorithmes.
#include <iostream>
using namespace std;
int count = 1;
int main() {
cout<<count<<endl;
}
je suis d'accord avec les autres, mais je voudrais aborder les préoccupations concernant la lisibilité - vous pouvez éviter tout cela en utilisant simplement des typographies en haut de votre fichier, fonction ou déclaration de classe.
Je l'utilise habituellement dans ma déclaration de classe comme méthodes dans une classe ont tendance à traiter des types de données similaires (les membres) et un typedef est une occasion d'attribuer un nom qui est significatif dans le contexte de la classe. Cela facilite en fait la lisibilité dans définitions des méthodes de classe.
//header
class File
{
typedef std::vector<std::string> Lines;
Lines ReadLines();
}
et dans la mise en œuvre:
//cpp
Lines File::ReadLines()
{
Lines lines;
//get them...
return lines;
}
par opposition à:
//cpp
vector<string> File::ReadLines()
{
vector<string> lines;
//get them...
return lines;
}
ou:
//cpp
std::vector<std::string> File::ReadLines()
{
std::vector<std::string> lines;
//get them...
return lines;
}
" pourquoi l'utilisation de namespace std est-elle considérée comme une mauvaise pratique en C++?"
je l'ai mis dans l'autre sens: Pourquoi taper 5 caractères est considéré comme lourd par certains?
envisager par exemple l'écriture d'un morceau de logiciel numérique, pourquoi est-ce que je considérerais même polluant mon espace de nom global en coupant général "std::vector" à "vector" alors que "vector" est l'un des concepts les plus importants du domaine de problème?
je ne pense pas que c'est nécessairement une mauvaise pratique dans toutes les conditions, mais vous devez être prudent lorsque vous l'utilisez. Si vous écrivez une bibliothèque, vous devriez probablement utiliser les opérateurs de résolution scope avec l'espace de noms pour empêcher votre bibliothèque de frapper des têtes avec d'autres bibliothèques. Pour le code de niveau d'application, Je ne vois rien de mal à ça.
pour répondre à votre question je le regarde de cette façon pratique: beaucoup de programmeurs (pas tous) invoquent l'espacenom std. Par conséquent, on devrait avoir l'habitude de ne pas utiliser des choses qui empiètent ou utilisent les mêmes noms que ce qui est dans la norme d'espace de noms. C'est un grand pas en avant, mais pas tellement par rapport au nombre possible de mots cohérents et de pseudonymes qui peuvent être proposés à proprement parler.
je veux dire vraiment... dire "Ne comptez pas sur cette présence" c'est juste la configuration de compter sur lui ne PAS être présent. Vous allez constamment avoir des problèmes en empruntant des bouts de code et en les réparant constamment. Il suffit de garder vos trucs définis par l'utilisateur et empruntés dans une portée limitée comme ils devraient l'être et d'être très économes avec les globals (honnêtement les globals devraient presque toujours être un dernier recours pour les fins de "compiler maintenant, la santé mentale plus tard"). Vraiment, je pense que c'est un mauvais conseil de votre enseignant parce que l'utilisation de MST fonctionnera à la fois pour "cut" et "std:: Cut", mais ne pas utiliser MST sera seulement travailler pour"std::cout". Vous ne serez pas toujours la chance d'écrire votre propre code.
NOTE: Ne vous focalisez pas trop sur les questions d'efficacité jusqu'à ce que vous en appreniez un peu plus sur le fonctionnement des compilateurs. Avec un peu d'expérience de codage, vous n'avez pas à apprendre beaucoup sur eux avant de vous rendre compte à quel point ils sont capables de généraliser le bon code dans quelque chose de simple. Tout aussi simple que si vous avez écrit tout ça en C. Bon code est aussi complexe comme elle doit l'être.
D'après mon expérience, si vous avez plusieurs bibliothèques qui utilisent dire, cout
, mais pour un but différent, vous pouvez utiliser le mauvais cout
.
par exemple, si je tape, using namespace std;
et using namespace otherlib;
et tapez juste cout (qui se trouve être dans les deux), plutôt que std::cout
(ou 'otherlib::cout'
), vous pourriez utiliser le mauvais, et obtenir des erreurs, il est beaucoup plus efficace et efficient d'utiliser std::cout
.
il s'agit d'une mauvaise pratique, souvent connue sous le nom de pollution de l'espace géographique. Des problèmes peuvent se produire lorsque plus d'un namespace a le même nom de fonction avec signature, alors il sera ambigu pour le compilateur de décider lequel appeler et tout cela peut être évité lorsque vous spécifiez le namespace avec votre appel de fonction comme std::cout
. Espérons que cette aide. :)
je suis d'accord avec les autres – il est demandé à la nom des affrontements, des ambiguïtés et puis, le fait est qu'il est moins explicite. Bien que je puisse voir l'utilisation de using
, ma préférence personnelle est de les limiter. Je voudrais aussi fortement considérer ce que d'autres ont souligné:
si vous voulez trouver un nom de fonction qui pourrait être un nom assez commun, mais vous voulez seulement le trouver dans l'espace de noms std
(ou l'inverse – vous voulez changer tous les appels qui ne sont pas dans l'espace de noms std
, l'espace de noms X
, ...), alors comment proposez-vous de faire cela? Vous pourriez écrire un programme pour le faire, mais ne serait-il pas préférable de passer du temps à travailler sur votre projet lui-même plutôt que d'écrire un programme pour maintenir votre projet?
personnellement, le préfixe std::
ne me dérange pas. J'aime le look plus que ne pas l'avoir. Je ne sais pas si c'est parce qu'elle est explicite et me dit: "ce n'est pas mon code... J'utilise la bibliothèque standard" ou si elle c'est autre chose, mais je pense que c'est plus agréable. Ce pourrait être étrange étant donné que je suis entré dans C++ (utilisé et encore do C et d'autres langues pour beaucoup plus longtemps et C est ma langue préférée de tous les temps, juste au-dessus de l'Assemblée).
il y a une autre chose bien qu'elle soit quelque peu liée à ce qui précède et à ce que d'autres soulignent. Bien que cela puisse être une mauvaise pratique, je réserve parfois std::name
pour la version de bibliothèque standard et le nom pour la mise en œuvre spécifique du programme. Oui en effet, cela pourrait vous mordre et vous mordre dur mais tout se résume à cela, j'ai commencé ce projet à partir de zéro et je suis le seul programmeur. Exemple: je surcharge std::string
et l'appelle string
. J'ai des ajouts utiles. Je l'ai fait en partie à cause de ma tendance C et Unix (+ Linux) vers des noms de minuscules.
en outre, vous pouvez avoir des alias d'espace de noms. Voici un exemple d'utilité qui n'a peut-être pas été mentionnée. J'utilise le C++11 standard et en particulier avec libstdc++. Eh bien, il n'a pas le soutien complet std::regex
. Bien sûr il compile mais il jette une exception dans le sens où il s'agit d'une erreur du côté du programmeur. Mais c'est le manque de mise en œuvre. Alors, voici comment je l'ai résolu. Installez le regex de Boost, liez-le. Ensuite, je fais ce qui suit pour que lorsque libstdc++ est entièrement implémenté, Je n'ai qu'à supprimer ce bloc et le code reste le même:
namespace std
{
using boost::regex;
using boost::regex_error;
using boost::regex_replace;
using boost::regex_search;
using boost::regex_match;
using boost::smatch;
namespace regex_constants = boost::regex_constants;
}
Je ne discuterai pas si c'est une mauvaise idée ou pas. Je vais cependant argumenter qu'il le garde propre pour mon projet et en même temps le rend spécifique: il est vrai que je dois utiliser Boost mais je l'utilise comme le libstdc++ finira par l'avoir. Oui, démarrer votre propre projet et commencer par une norme (...) au tout début, cela va très loin avec l'aide à la maintenance, au développement et à tout ce qui est impliqué dans le projet!
Edit:
Maintenant que j'ai le temps, juste pour clarifier quelque chose. Je ne pense pas vraiment que ce soit une bonne idée d'utiliser un nom de classe/n'importe quoi dans le STL délibérément et plus spécifiquement à la place de. La chaîne est l'exception (ignorez la première, ci-dessus, ou la deuxième ici, jeu de mots si vous devez) pour moi que je n'ai pas aimé l'idée de "chaîne". Comme il est, je suis encore très biaisé vers C et biaisé contre C++. (Mais c'était un bon exercice et une bonne façon de me faire un. apprendre une autre langue et B. essayez de ne pas être moins partial contre objet/classes/etc qui est peut-être mieux énoncé comme moins fermé d'esprit, moins arrogant, plus acceptant.). Mais ce qui est utile, c'est ce que certains ont déjà suggéré: j'utilise en effet la liste (elle est assez générique, n'est-elle pas ?), trier (même chose) pour en nommer deux qui causeraient un conflit de nom si je devais faire using namespace std;
et à cette fin, je préfère être spécifique, en contrôle et sachant que si j'ai l'intention que ce soit l'utilisation standard, alors je vais devoir la spécifier. Disons-le simplement: pas de supposer permis.
et comme pour faire de la regex de Boost une partie de std
. Je le fais pour l'intégration future et-encore une fois, je l'admets totalement - Je ne pense pas que ce soit aussi laid que boost::regex:: ...
en effet, c'est une autre chose pour moi. Il y a beaucoup de choses en C++ que je n'ai pas encore totalement acceptées dans les looks et les méthodes (un autre exemple: les gabarits variadic versus var args [même si j'admets que les gabarits variadic sont très très utiles!]). Même ceux que j'accepte ont été difficiles et j'ai encore des problèmes avec eux.
il ne rend pas pire votre logiciel ou la performance du projet, l'inclusion de l'espace de nom au début de votre code source n'est pas mauvais. L'inclusion de l'instruction using namespace std
varie selon vos besoins et la façon dont vous développez le Logiciel ou le projet.
le namespace std
contient les fonctions et variables standard C++. Cet espace-nom est utile lorsque vous utilisez souvent les fonctions standard C++.
comme il est mentionné dans ce page :
l'énoncé utilisant namespace std est généralement considéré comme mauvais pratique. L'alternative à cette déclaration est de spécifier namespace auquel appartient l'identifiant en utilisant l'opérateur scope(::) chaque fois que nous déclarons un type.
et voir cette opinion :
il n'y a aucun problème à utiliser "using namespace std" dans votre fichier source lorsque vous faites un usage intensif de l'espace de noms, et je sais que rien ne va entrer en collision.
certaines personnes avaient dit que c'était une mauvaise pratique d'inclure le using namespace std
dans vos fichiers source parce que vous invoquez à partir de cet espace de noms toutes les fonctions et variables. Lorsque vous souhaitez définir une nouvelle fonction avec le même nom qu'une autre fonction contenue dans le namespace std
, vous surchargez la fonction et elle pourrait produire des problèmes dus à la compilation ou de l'exécution. Il ne compilera ni n'exécutera comme vous l'attendez.
comme il est mentionné dans ce page :
bien que la déclaration nous évite de taper std:: whenever nous souhaitons accéder à une classe ou un type défini dans l'espace de noms std, il importe la totalité de l'espace de noms std dans l'espace de noms courant de le programme. Prenons quelques exemples pour comprendre pourquoi cette peut-être pas une bonne thing
...
Maintenant à un stade ultérieur du développement, nous souhaitons utiliser une autre version de cout qui est personnalisé mis en œuvre dans une bibliothèque appelée "foo" (pour exemple)
...
remarquez qu'il y a une ambiguïté, à quelle bibliothèque renvoie cout? Le compilateur peut détecter cela et ne pas compiler le programme. Dans le pire des cas, le programme peut encore compiler mais d'appeler la fonction incorrecte, depuis nous n'avons jamais spécifié à l'identificateur d'espace de noms appartenaient.
avec des identificateurs importés non qualifiés vous avez besoin d'outils de recherche externes comme grep pour trouver où les identificateurs sont déclarés. Cela rend le raisonnement sur la justesse du programme plus difficile.
cela dépend de son emplacement. Si c'est un en-tête commun, alors vous diminuez la valeur de l'espace de noms en le fusionnant dans l'espace de noms global. Gardez à l'esprit, ce pourrait être une façon soignée de faire des modules globals.