Pourquoi "utiliser l'espace de noms std;" considéré comme une mauvaise pratique?

2642

D'autres m'ont dit que l'écriture using namespace std;dans le code est incorrecte et que je devrais utiliser std::coutet std::cindirectement à la place.

Pourquoi est-ce using namespace std;considéré comme une mauvaise pratique? Est-ce inefficace ou risque-t-il de déclarer des variables ambiguës (variables qui partagent le même nom qu'une fonction dans l' stdespace de noms)? Cela a-t-il un impact sur les performances?

akbiggs
la source
513
N'oubliez pas que vous pouvez faire: "using std :: cout;" ce qui signifie que vous n'avez pas besoin de taper std :: cout, mais que vous n'introduisez pas tout l'espace de noms std en même temps.
Projet de loi du
2
@un nerd payant google-styleguide.googlecode.com/svn/trunk/… ne fonctionne plus. On dirait que le nouveau lien est google.github.io/styleguide/cppguide.html#Other_C++_Features
MCG
64
Il est particulièrement mauvais d'utiliser «using namespace std» à la portée du fichier dans les fichiers d'en-tête. L'utiliser dans les fichiers source (* .cpp) à la portée du fichier après tout n'est pas aussi mauvais, car son effet est limité à une seule unité de traduction. Il est encore moins problématique de l'utiliser à l'intérieur de fonctions ou de classes, car son effet est limité à la portée de la fonction ou de la classe.
sh-
5
Je déconseille d'utiliser avec la directive , mais pour les espaces de noms spécifiques comme std::literals::chrono_literals, Poco::Data:Keywords, Poco::Unitset d'autres choses qui traitera des littéraux ou des astuces de lisibilité. Chaque fois qu'il se trouve dans des fichiers d'en-tête ou d'implémentation. Cela pourrait être OK dans une portée de fonction, je suppose, mais à part les littéraux et les trucs, ce n'est pas utile.
Ludovic Zenohate Lagouardette
7
@ Jon: Cela n'a rien à voir avec l'espace de noms std en particulier. Mon accent devait être mis sur «à la portée du fichier dans les fichiers d'en-tête». Pour le mettre comme conseil: N'utilisez pas "using namespace" (std ou autre) à la portée du fichier dans les fichiers d'en-tête. Il est correct de l'utiliser dans les fichiers d'implémentation. Désolé pour l'ambiguïté.
sh-

Réponses:

2231

Ce n'est pas du tout lié aux performances. Mais considérez ceci: vous utilisez deux bibliothèques appelées Foo et Bar:

using namespace foo;
using namespace bar;

Tout fonctionne bien, et vous pouvez appeler Blah()de Foo et Quux()de Bar sans problème. Mais un jour, vous passez à une nouvelle version de Foo 2.0, qui propose désormais une fonction appelée Quux(). Vous avez maintenant un conflit: Foo 2.0 et Bar importent Quux()dans votre espace de noms global. Cela va prendre un certain effort à résoudre, surtout si les paramètres de fonction correspondent.

Si vous aviez utilisé foo::Blah()et bar::Quux(), alors l'introduction de foo::Quux()aurait été un non-événement.

Greg Hewgill
la source
435
J'ai toujours aimé "importer big_honkin_name en tant que bhn" de Python, vous pouvez donc simplement utiliser "bhn.something" plutôt que "big_honkin_name.something" - ce qui réduit vraiment la frappe. Est-ce que C ++ a quelque chose comme ça?
paxdiablo
764
@Pax namespace io = boost :: filesystem;
AraK
152
Je pense que c'est exagérer les choses de dire que c'est "un effort pour réparer". Vous n'aurez aucune instance du nouveau foo :: Quux, alors il suffit de lever l'ambiguïté de toutes vos utilisations actuelles avec bar :: Quux.
MattyT
289
Une personne sensée créerait-elle une bibliothèque avec des types dont le nom non qualifié entre en collision avec les types std?
erikkallen
94
@TomA: Le problème #defineest qu'il ne se limite pas aux espaces de noms, mais piétine toute la base de code. Un alias d'espace de noms est ce que vous voulez.
sbi
1391

Je suis d'accord avec tout ce que Greg a écrit , mais j'aimerais ajouter: cela peut même empirer ce que Greg a dit!

La bibliothèque Foo 2.0 pourrait introduire une fonction, Quux()qui correspond sans aucun doute mieux à certains de vos appels Quux()que le bar::Quux()code appelé depuis des années. Ensuite, votre code compile toujours , mais il appelle silencieusement la mauvaise fonction et fait quoi que ce soit. C'est aussi mauvais que les choses peuvent arriver.

Gardez à l' esprit que l' stdespace de noms a des tonnes d'identificateurs, dont beaucoup sont très plus communs (penser list, sort, string, iterator, etc.) qui sont très susceptibles d'apparaître dans tout autre code, aussi.

Si vous considérez cela comme improbable: Il y avait une question posée ici sur Stack Overflow où à peu près exactement cela s'est produit (mauvaise fonction appelée en raison du std::préfixe omis ) environ six mois après avoir donné cette réponse. Voici un autre exemple plus récent d'une telle question. C'est donc un vrai problème.


Voici un autre point de données: il y a de nombreuses années, je trouvais également ennuyeux de devoir tout préfixer de la bibliothèque standard avec std::. Ensuite, j'ai travaillé dans un projet où il a été décidé au début que les usingdirectives et les déclarations étaient interdites, sauf pour les étendues de fonction. Devine quoi? La plupart d'entre nous ont mis très peu de semaines à s'habituer à écrire le 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: que vous aimiez une prose plus ou moins longue est subjectif, mais les préfixes ajoutent objectivement de la clarté au code. Non seulement le compilateur, mais vous aussi, trouvez plus facilement à quel identifiant il est fait référence.

En une décennie, ce projet s'est développé pour compter plusieurs millions de lignes de code. Étant donné que ces discussions reviennent encore et encore, j'ai été curieux de savoir à quelle fréquence la fonction (autorisée) usingétait réellement utilisée dans le projet. J'ai recherché les sources et trouvé seulement une ou deux douzaines d'endroits où il était utilisé. Pour moi, cela indique qu'une fois essayé, les développeurs ne trouvent pas std::assez pénible d'utiliser des directives, même une fois tous les 100 kLoC, même là où il a été autorisé à les utiliser.


Conclusion: préfixer explicitement tout ne fait pas de mal, demande très peu de temps pour s'y habituer et présente des avantages objectifs. En particulier, cela rend le code plus facile à interpréter par le compilateur et par les lecteurs humains - et cela devrait probablement être l'objectif principal lors de l'écriture de code.

sbi
la source
140
Cela nuit considérablement à la densité de code que vous pouvez emballer sur une seule ligne. Vous finissez par écrire votre code de manière très longue; ce qui réduit la lisibilité. Personnellement, je pense que le code plus court (mais pas trop court) a tendance à être plus lisible (car il y a moins de choses à lire et moins de choses à distraire).
Lie Ryan
92
Je suppose que vous avez manqué les anciens jours avant que C ++ n'ait une stringclasse standard , et apparemment chaque bibliothèque avait la sienne. Dites-vous quoi: Nous continuerons d'écrire notre code avec std::, et vous pourrez exécuter notre code tout au long de grep -v std:: | vimvotre navigation. Ou vous pouvez apprendre à votre éditeur std::un mot-clé qui doit être coloré de la même manière que la couleur d'arrière-plan. Tout ce qui fonctionne.
Mike DeSimone
80
Je ne pense pas que ce std::soit nocif du tout. Il contient des informations très importantes (à savoir "tout ce qui vient après fait partie de la bibliothèque standard", et c'est toujours un préfixe assez court et compact. La plupart du temps, ce n'est pas un problème du tout. Parfois, vous avez quelques lignes de code où vous devez souvent faire référence à des symboles spécifiques dans l' stdespace de noms, puis une usingdéclaration dans cette portée particulière résout bien le problème. Mais dans le cas général, ce n'est pas du bruit, il transmet des informations précieuses en plus de lever les ambiguïtés.
jalf
147
Chaque fois que je vois std::, je sais que ça va venir std::sans avoir à y penser. Si je vois stringou listou mappar eux-mêmes, je me demande un peu.
Mateen Ulhaq
68
@LieRyan Alors bonne chance pour écrire une bibliothèque de géométrie sans jamais nommer quelque chose vector, transformou distance. Et ce ne sont que des exemples des nombreux noms très courants utilisés dans la bibliothèque standard. Il est plutôt contre-productif de suggérer de ne pas les utiliser par peur ou par une opinion biaisée de la fonctionnalité d'espace de noms qui fait partie intégrante de C ++.
Christian Rau
420

Le problème avec la mise using namespacedans les fichiers d'en-tête de vos classes est qu'il oblige quiconque veut utiliser vos classes (en incluant vos fichiers d'en-tête) à «utiliser» (c'est-à-dire tout voir) dans ces autres espaces de noms.

Cependant, vous pouvez vous sentir libre de mettre une instruction using dans vos fichiers (privés) * .cpp.


Attention, certaines personnes ne sont pas d'accord avec mon énoncé "n'hésitez pas" comme ceci - parce que même si une usingdéclaration dans un fichier cpp est meilleure que dans un en-tête (car elle n'affecte pas les personnes qui incluent votre fichier d'en-tête), ils pensent que ce n'est toujours pas le cas bon (car en fonction du code, cela pourrait rendre l'implémentation de la classe plus difficile à maintenir). Cette entrée C ++ Super-FAQ dit,

La directive using existe pour le code C ++ hérité et pour faciliter la transition vers les espaces de noms, mais vous ne devriez probablement pas l'utiliser régulièrement, du moins pas dans votre nouveau code C ++.

La FAQ propose deux alternatives:

  • Une déclaration d'utilisation:

    using std::cout; // a using-declaration lets you use cout without qualification
    cout << "Values:";
  • Il suffit de taper std ::

    std::cout << "Values:";
ChrisW
la source
1
Bien sûr, vous ne devriez jamais non plus supposer l'état du cout global, de peur que quelqu'un ait std: cout << std :: hex et échoue ensuite à std :: restore_cout_state. Mais c'est un tout autre fatberg.
Móż
233

J'ai récemment rencontré une plainte concernant Visual Studio 2010 . Il s'est avéré que presque tous les fichiers source avaient ces deux lignes:

using namespace std;
using namespace boost;

De nombreuses fonctionnalités Boost sont intégrées dans la norme C ++ 0x, et Visual Studio 2010 possède de nombreuses fonctionnalités C ++ 0x, donc soudainement ces programmes ne se compilaient pas.

Par conséquent, en évitant using namespace X; est une forme de pérennisation, un moyen de s'assurer qu'une modification des bibliothèques et / ou des fichiers d'en-tête utilisés ne va pas casser un programme.

David Thornley
la source
14
Cette. Boost et std se chevauchent beaucoup - en particulier depuis C ++ 11.
einpoklum
1
Je l'ai fait une fois et j'ai appris une leçon à la dure. Maintenant, je n'utilise jamais en usingdehors d'une définition de fonction et j'utilise rarement using namespacedu tout.
Ferruccio
210

Version courte: n'utilisez pas de usingdéclarations ou directives globales dans les fichiers d'en-tête. N'hésitez pas à les utiliser dans les fichiers d'implémentation. Voici ce que Herb Sutter et Andrei Alexandrescu ont à dire à propos de ce problème dans les normes de codage C ++ (les caractères gras sont les miens):

Sommaire

Les utilisations des espaces de noms sont pour votre commodité, pas pour que vous les infligiez aux autres: N'écrivez jamais une déclaration using ou une directive using avant une directive #include.

Corollaire: dans les fichiers d'en-tête, n'écrivez pas au niveau de l'espace de noms à l'aide de directives ou de déclarations; à la place, qualifiez explicitement tous les noms. (La deuxième règle découle de la première, car les en-têtes ne peuvent jamais savoir quels autres en-têtes #includes pourraient apparaître après eux.)

Discussion

En bref: vous pouvez et devez utiliser l'espace de noms à l'aide de déclarations et de directives généreusement dans vos fichiers d'implémentation après les directives #include et vous en sentir bien. Malgré les affirmations répétées du contraire, l'espace de noms utilisant des déclarations et des directives n'est pas mauvais et ne va pas à l'encontre de l'objectif des espaces de noms. C'est plutôt ce qui rend les espaces de noms utilisables .

mattnewport
la source
4
Juste une opinion de programmeur de plus ici, mais bien que je sois d'accord à 100% avec l'affirmation selon laquelle le mot usingne devrait jamais apparaître dans un en-tête, je ne suis pas aussi convaincu de la licence gratuite à placer using namespace xyz;n'importe où dans votre code, surtout si xyzc'est le cas std. J'utilise le using std::vector;formulaire, car cela ne tire qu'un seul élément de l'espace de noms dans une portée pseudo-globale, ce qui entraîne donc beaucoup moins de risques de collision.
dgnuff
2
@Lightness Races in Orbit vous avez bien sûr droit à votre opinion. Il aurait été plus utile de tenter d'expliquer pourquoi vous n'êtes pas d'accord avec les conseils donnés dans cette réponse. Il serait particulièrement intéressant de comprendre quel est l'intérêt des espaces de noms si les «utiliser» est mauvais? Pourquoi ne pas simplement nommer les choses std_cout au lieu de std :: cout ... les créateurs de C ++ / namespace doivent avoir eu une idée quand ils ont pris la peine de les créer.
nyholku
1
@nyholku: Pas besoin - la majorité des autres réponses donnent les mêmes raisons que moi. N'hésitez pas non plus à noter le ":)" que j'ai joint à mon commentaire! Et que je n'ai pas dit que les espaces de noms sont mauvais.
Courses de légèreté en orbite
Oui, je l'ai remarqué :) mais l'OMI la majorité des réponses (qui vont à l'encontre de ce sage conseil) sont erronées (pas que j'ai fait des statistiques quelle est la majorité maintenant). Si vous êtes d'accord pour dire que l'espace de noms n'est «pas mauvais», vous pourriez dire où vous pensez qu'ils sont appropriés si vous n'êtes pas d'accord avec cette réponse?
nyholku
Je ne peux pas m'empêcher de sentir que using namespacec'est mal comme gotoc'est mal. Les deux ont des utilisations valides, mais 999 fois sur 1000, ils seront mal utilisés. Donc, oui, avec using namespacela source, vous ne polluerez pas l'espace de noms des autres inclus, bien. Mais cela ne vous protègera toujours pas contre le "plaisir" qui découle de using namespace Foo+ using namespace Baravec votre appel (Foo implicite: :) baz(xyz)et soudainement la rupture du code (sans changements associés) simplement parce que Bar::baz()ajouté quelque part, ce qui se trouve être un meilleur match (et est donc désormais appelé à la place)
CharonX
122

Il ne faut pas utiliser la usingdirective à l'échelle mondiale, en particulier dans les en-têtes. Cependant, 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...), car elle est plus courte et a la capacité de travailler avec des types à virgule flottante définis par l'utilisateur (via la recherche dépendante de l'argument (ADL)).

robson3.14
la source
9
Je suis désolé, mais je suis fortement en désaccord avec cela.
Billy ONeal
4
@Billy: Il n'y a pas d'autre moyen de supporter l'appel de userlib :: cos (userlib :: superint). Chaque fonctionnalité a une utilité.
Zan Lynx
17
@Zan: Bien sûr qu'il y en a. using std::cos;, using std::sinEtc. La question est bien que tout bien conçu userlibva avoir leur sinet cosdans leur propre espace de noms aussi bien, donc cela ne vraiment pas vous aider. (À moins qu'il y ait un using namespace userlibavant ce modèle et que ce soit aussi mauvais que using namespace std- et la portée là-bas n'est pas limitée.) En outre, la seule fonction comme celle-ci que je vois jamais arriver est swap, et dans de tels cas, je recommanderais simplement de créer un modèle spécialisation std::swapet éviter tout le problème.
Billy ONeal
11
@BillyONeal: template<typename T> void swap(MyContainer<T>&, MyContainer<T>&)(Il n'y a pas de spécialisation partielle de modèle de fonction (FTPS), donc parfois vous devez recourir à la surcharge à la place.
sbi
38
@BillyONeal: Votre commentaire (voté 7 fois!) Est faux - la situation que vous décrivez est exactement ce que ADL a été conçu pour couvrir. En bref, six a un ou plusieurs "espaces de noms associés" (par exemple, s'il a été défini dans namespace userlib), alors tout appel de fonction qui ressemble cos(x)apparaîtra également dans ces espaces de noms - sans qu'aucun using namespace userlib;préalable ne soit nécessaire. Zan Lynx a raison (et la recherche de nom C ++ est byzantine ...)
j_random_hacker
97

Ne l'utilisez pas globalement

Il est considéré comme «mauvais» uniquement lorsqu'il est utilisé à l'échelle mondiale . Parce que:

  • Vous encombrez l'espace de noms dans lequel vous programmez.
  • Les lecteurs auront du mal à voir d'où vient un identifiant particulier, lorsque vous en utilisez plusieurs using namespace xyz.
  • Ce qui est vrai pour les autres lecteurs de votre code source l'est encore plus pour le lecteur le plus fréquent: vous-même. Revenez dans un an ou deux et jetez un œil ...
  • Si vous ne parlez que de using namespace stdvous, vous pourriez ne pas être au courant de toutes les choses que vous saisissez - et lorsque vous en ajoutez une autre #includeou passez à une nouvelle révision C ++, vous risquez d'obtenir des conflits de noms dont vous n'étiez pas au courant.

Vous pouvez l'utiliser localement

Allez-y et utilisez-le localement (presque) librement. Cela, bien sûr, vous empêche de répéterstd:: - et la répétition est également mauvaise.

Un idiome pour l'utiliser localement

En C ++ 03, il y avait un idiome - code passe-partout - pour implémenter une swapfonction pour vos classes. Il a été suggéré que vous utilisiez réellement un local using namespace std- 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 compilateur choisira le std::swapfor value_, c'est-à-direvoid std::swap(int, int) .
  • Si vous avez une surcharge void swap(Child&, Child&) implémentée, le compilateur la choisira.
  • Si tu fais pas cette surcharge, le compilateur les utilisera void std::swap(Child&,Child&)et essaiera de les échanger au mieux.

Avec C ++ 11, il n'y a plus de raison d'utiliser ce modèle. L'implémentation de a std::swapété modifiée pour trouver une surcharge potentielle et la choisir.

towi
la source
5
"L'implémentation de std :: swap a été modifiée pour trouver une surcharge potentielle et la choisir." - Quoi? Êtes-vous sûr de cela? Bien qu'il soit vrai que fournir une coutume swapen premier lieu n'est plus très important en C ++ 11, car le std::swaplui-même est plus flexible (utilise la sémantique de déplacement). Mais std::swapchoisir automatiquement votre propre swap personnalisé, c'est absolument nouveau pour moi (et je n'y crois pas vraiment).
Christian Rau
@ChristianRau Je pense que oui. J'ai lu ça sur SO quelque part. On peut toujours demander à Howard , il devrait savoir. Je suis en train de creuser et de creuser maintenant ...
towi
14
Même dans le cas du swap, l'idiome le plus clair (et heureusement plus commun) est d'écrire using std::swap;plutôt que using namespace std;. L'idiome plus spécifique a moins d'effets secondaires et rend donc le code plus maintenable.
Adrian McCarthy
11
La dernière phrase est fausse. En C ++ 11, le Std Swap Two Step a été officiellement béni comme la bonne façon d'appeler swap, et divers autres endroits de la norme ont été modifiés pour dire qu'ils appellent swapcomme ça (NB comme indiqué ci-dessus, using std::swapc'est la bonne façon, non using namespace std). Mais std::swaplui-même n'a absolument pas changé pour en trouver un autre swapet l'utiliser. Si std::swapest appelé, il std::swaps'habitue.
Jonathan Wakely
3
Il peut cependant être plus judicieux de taper using std::swaplocalement pour réduire l'espace de noms local tout en créant du code auto-documenté. Vous êtes rarement intéressé par tout l'espace de noms std, alors choisissez simplement les parties qui vous intéressent.
Lundin
79

Si vous importez les fichiers d' en- tête de droite , vous avez soudainement des noms comme hex, left, plusou countdans votre portée globale. Cela peut être surprenant si vous ne savez pas qui std::contient ces noms. Si vous essayez également d'utiliser ces noms localement, cela peut entraîner une certaine confusion.

Si tous les éléments standard se trouvent dans son propre espace de noms, vous n'avez pas à vous soucier des collisions de noms avec votre code ou d'autres bibliothèques.

qch
la source
12
+1 sans parler distance. Je préfère toujours les noms non qualifiés dans la mesure du possible, car cela augmente la lisibilité pour moi. De plus, je pense que le fait que nous ne qualifions généralement pas les choses dans le discours oral et que nous sommes prêts à passer du temps à résoudre les ambiguïtés possibles, signifie qu'il a une valeur pour être en mesure de comprendre ce dont on parle sans qualifications et appliqué à la source code qui signifie qu'il est structuré de telle manière qu'il est clair de quoi il s'agit, même sans qualifications.
Bravo et hth. - Alf
Pour être juste, cependant, vous n'en avez pas la plupart si vous n'incluez pas <iomanip>. Encore un bon point.
einpoklum
48

Une autre raison est la surprise.

Si je vois cout << blah, au lieu de std::cout << blahje pense: qu'est-ce que c'est cout? Est-ce normal cout? Est-ce quelque chose de spécial?

Martin Beckett
la source
25
Est-ce une farce? Je ne peux vraiment pas le dire. Sinon, je suppose personnellement que c'est le `` cout '' normal, sauf si vous ne faites pas confiance au code, sinon ce serait une odeur de code AU-DELÀ MAJEURE, IMO. ... Et si vous ne faites pas confiance au code, pourquoi l'utilisez-vous en premier lieu? Notez que je ne dis pas "FAITES CONFIANCE À TOUT !!" mais cela semble aussi un peu exagéré si vous traitez, disons, avec une bibliothèque bien connue de GitHub ou quelque chose.
Brent Rittenhouse
28
@BrentRittenhouse coutest un mauvais exemple car tout le monde le reconnaît. Mais imaginez futuredans une application financière. Est-ce un contrat pour acheter ou vendre quelque chose à une date spécifiée? Non ça ne l'est pas. Si le code disait que std::futurevous ne seriez pas si facilement confondu.
James Hollis
2
@BrentRittenhouse peut-être un petit mauvais exemple, il y a au moins quatre bibliothèques différentes qui ont cout. Peut-être "est-ce une bibliothèque standard? Libstdc ++? Stl? Autre chose?" Et non, tout le monde ne connaît pas std :: cout, au moins intrinsèquement, 6 des 7 nouveaux travailleurs que nous recevons ne le savent pas. Parce que les programmes d'enseignement n'utilisent pas ceux de l'éducation. Je dois chasser les printfs. Ou debugs () - de Qt.
Swift - Friday Pie
1
Vraiment? C'est à peu près dans le premier exemple du premier chapitre de tant de livres sur C ++, si quoi que ce soit (avec l'utilisation de l'opérateur d'insertion) est le seul C ++ que certains nouveaux bods connaissent.
mckenzm
@mckenzm Je pourrais le mettre dans un livre ou des notes de cours pour réduire l'encombrement, mais pas dans le code
Martin Beckett
45

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'utilisation au niveau du fichier d'en-tête pour cette raison exacte.

Les programmeurs expérimentés tentent également d'éviter la qualification complète des noms dans leurs fichiers source. Une raison mineure à cela est qu'il n'est pas élégant d'écrire plus de code lorsque moins de code est suffisant, sauf s'il existe de bonnes raisons . Une raison principale à cela est la désactivation de la recherche dépendante des arguments (ADL).

Quelles sont ces bonnes raisons ? Parfois, les programmeurs veulent explicitement désactiver ADL, d'autres fois ils veulent lever l'ambiguïté.

Donc, ce qui suit est OK:

  1. Directives d'utilisation et déclarations d'utilisation au niveau des fonctions dans les implémentations des fonctions
  2. Déclarations d'utilisation au niveau du fichier source dans les fichiers source
  3. (Parfois) directives d'utilisation au niveau du fichier source
Alexander Poluektov
la source
43

Je suis d'accord qu'il ne devrait pas être utilisé globalement, mais ce n'est pas si mal d'utiliser localement, comme dans a namespace. Voici un exemple de "The C ++ Programming Language" :

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 résultant de leur composition.

Les noms qui y sont explicitement déclarés (y compris les noms déclarés par des déclarations using comme His_lib::String) ont priorité sur les noms rendus accessibles dans une autre portée par une directive using ( using namespace Her_lib).

Oleksiy
la source
29

Je considère également que c'est une mauvaise pratique. Pourquoi? Un jour, j'ai pensé que la fonction d'un espace de noms était de diviser des choses, donc je ne devrais pas le gâcher en jetant tout dans un seul 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 sain d'esprit ne nommera jamais un flux coutou cin. ;)

Yelonek
la source
7
C'est une déclaration using locale , une chose très différente d'une directive using .
sbi
25

C'est agréable de voir le code et de savoir ce qu'il fait. Si je vois, std::coutje sais que c'est lecout flux de la stdbibliothèque. Si je vois, coutje ne sais pas. Ce pourrait être le coutflux de la stdbibliothèque. Ou il pourrait y avoir int cout = 0;dix lignes plus haut dans la même fonction. Ou une staticvariable nomméecout dans ce fichier. Ça pourrait être n'importe quoi.

Maintenant, prenez une base de code d'un million de lignes, ce qui n'est pas particulièrement gros, et vous recherchez un bogue, 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 intnom cout, le déplacer d'un bit vers la gauche et jeter le résultat. Vous cherchez un bug, je devrais vérifier cela. Pouvez-vous voir comment je préfère vraiment voirstd::cout ?

C'est une de ces choses qui semble vraiment une bonne idée si vous êtes un enseignant et que vous n'avez jamais eu à écrire et à maintenir un code pour vivre. J'adore voir du code où (1) je sais ce qu'il fait; et, (2) je suis convaincu que la personne qui l'écrit savait ce qu'il fait.

gnasher729
la source
4
Comment savez-vous que "std :: cout << 1" ne lit pas un int statique nommé cout dans l'espace de noms std en le décalant de un et en jetant le résultat? Aussi comment savez-vous ce que fait "<<";) ??? ... semble que cette réponse ne soit pas un bon point de données pour éviter «d'utiliser».
nyholku
4
Si quelqu'un a redéfini std :: cout pour qu'il soit un entier, alors votre problème n'est pas technique, mais social - quelqu'un l'a pour vous. (et vous devriez probablement aussi vérifier tous les en-têtes pour des choses comme #define true false, etc)
Jeremy Friesner
2
Quand je vois cout, je sais que c'est std :: cout, toujours. Si je me trompe, c'est le problème de la personne qui a écrit ce code, pas moi :)
Tien Do
22

Il s'agit de gérer la complexité. L'utilisation de l'espace de noms entraînera des choses que vous ne voulez pas, et donc rendra peut-être plus difficile le débogage (je dis peut-être). Utiliser std :: partout est plus difficile à lire (plus de texte et tout ça).

Chevaux pour les cours - gérez votre complexité comme vous le pouvez et sentez-vous le mieux possible.

Preet Sangha
la source
18

Considérer

// myHeader.h
#include <sstream>
using namespace std;


// someoneElses.cpp/h
#include "myHeader.h"

class stringstream {  // Uh oh
};

Notez que ceci est un exemple simple. Si vous avez des fichiers avec 20 inclusions et autres importations, vous aurez une tonne de dépendances à traverser pour comprendre le problème. Le pire, c'est que vous pouvez obtenir des erreurs non liées dans d'autres modules en fonction des définitions 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 bien de le faire dans des portées très limitées, mais je n'ai jamais eu de problème à taper les cinq caractères supplémentaires pour clarifier d'où viennent mes fonctions.

Ron Warholic
la source
18
  1. Vous devez être capable de lire du code écrit par des personnes qui ont des opinions de style et de meilleures pratiques différentes de vous.

  2. Si vous utilisez uniquement cout, personne ne se trompe. Mais lorsque vous avez beaucoup d'espaces de noms qui volent et que vous voyez cette classe et que vous n'êtes pas exactement sûr de ce qu'elle fait, avoir l'espace de noms explicite agit en quelque sorte comme un commentaire. Vous pouvez voir à première vue, "oh, c'est une opération de système de fichiers" ou "qui fait des trucs de réseau".

Dustin Getz
la source
17

L'utilisation de nombreux espaces de noms en même temps est évidemment une recette pour un désastre, mais en utilisant l'espace de noms JUST stdet uniquement l'espace de nomsstd n'est pas si grave à mon avis car la redéfinition ne peut se produire que par votre propre code ...

Il suffit donc de les considérer comme des fonctions réservées comme "int" ou "classe" et c'est tout.

Les gens devraient cesser d'être si anaux à ce sujet. Votre professeur avait raison depuis le début. Utilisez simplement UN espace de noms; c'est tout l'intérêt d'utiliser les espaces de noms en premier lieu. Vous n'êtes pas censé en utiliser plusieurs en même temps. A moins que ce ne soit le vôtre. Encore une fois, la redéfinition ne se produira pas.

user2645752
la source
La création de collisions n'est pas si dure - des chaînes courtes comme min, endet lessapparaissent dans l' std::espace de noms. Mais de plus, maintenant qu'il std::contient des milliers de symboles, il est utile pour le lecteur de savoir d'où vient un nouveau symbole qu'il ne connaît peut-être pas.
Tom Swirly
L'espace de noms std existe parce que les gens, que ce soit vous, vos collègues ou les personnes qui écrivent le middleware que vous utilisez, ne sont pas toujours avisés de mettre des fonctions à l'intérieur des espaces de noms. Ainsi, vous pouvez importer tout std :: et rien d'autre, tout en invoquant une collision entre, disons, std :: min et legacy :: min () de quelqu'un d'autre d'avant le moment où il était dans std.
Aiken Drum
14

Je suis d'accord avec les autres ici, mais je voudrais répondre aux préoccupations concernant la lisibilité - vous pouvez éviter tout cela en utilisant simplement des typedefs en haut de votre fichier, fonction ou déclaration de classe.

Je l'utilise généralement dans ma déclaration de classe car les méthodes d'une classe ont tendance à traiter des types de données similaires (les membres) et un typedef est une opportunité pour attribuer un nom significatif dans le contexte de la classe. Cela facilite en fait la lisibilité dans les 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;
}
Carl
la source
Juste un commentaire mineur, bien que typedef soit utile, j'envisagerais de créer une classe qui représente Lines au lieu d'utiliser typedef.
Eyal Solnik
14

Un exemple concret pour clarifier la préoccupation. Imaginez que vous ayez une situation où vous avez deux bibliothèques fooet barchacune avec son propre espace de noms:

namespace foo {
    void a(float) { /* Does something */ }
}

namespace bar {
    ...
}

Supposons maintenant que vous utilisez fooet barensemble 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, il «fait quelque chose». Mais plus tard, vous mettez à jour baret disons qu'il a changé pour ressembler à:

namespace bar {
    void a(float) { /* Does something completely different */ }
}

À ce stade, vous obtiendrez une erreur de compilation:

using namespace foo;
using namespace bar;

void main() {
    a(42);  // error: call to 'a' is ambiguous, should be foo::a(42)
}

Vous aurez donc besoin de faire un peu de maintenance pour clarifier que «a» signifiait foo::a. Ce n'est pas souhaitable, 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ù la barre a changé à la place pour ressembler à ceci:

namespace bar {
    void a(int) { /* Does something completely different */ }
}

À ce stade, votre appel à a(42)se lie soudainement à la bar::aplace de foo::aet au lieu de faire «quelque chose», il fait «quelque chose de complètement différent». Aucun avertissement du compilateur ou quoi que ce soit. Votre programme commence juste silencieusement à faire quelque chose de complètement différent qu'auparavant.

Lorsque vous utilisez un espace de noms, vous risquez un scénario comme celui-ci, c'est pourquoi les gens ne sont pas à l'aise avec les espaces de noms. Plus il y a de choses dans un espace de noms, plus le risque de conflit est grand, donc les gens pourraient être encore plus mal à l'aise d'utiliser l'espace de nomsstd (en raison du nombre de choses dans cet espace de noms) que les autres espaces de noms.

En fin de compte, il s'agit d'un compromis entre l'écritabilité et la fiabilité / maintenabilité. La lisibilité peut également prendre en compte, mais je pouvais voir des arguments pour que cela aille dans les deux sens. 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 relativement rare sur la fiabilité / maintenabilité. Le «meilleur» compromis déterminera votre projet et vos priorités.

Kevin
la source
Le deuxième scénario conclut l'accord pour moi. Aucun espace de noms à nouveau. Ne peut pas avoir de tels changements subtils dans les fonctionnalités sans être détectés sous le capot.
safe_malloc
13

Un espace de noms est une étendue nommée. Les espaces de noms sont utilisés pour regrouper les déclarations liées et pour séparer les éléments séparés. Par exemple, deux bibliothèques développées séparément peuvent utiliser le même nom pour faire référence à des éléments différents, 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
    // ...
}

La répétition d'un nom d'espace de noms peut être une distraction pour les lecteurs et les écrivains. Par conséquent, il est possible d'indiquer que les noms d'un espace de noms particulier sont disponibles sans qualification explicite. 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
    // ...
}

Les espaces de noms fournissent un outil puissant pour la gestion de différentes bibliothèques et de différentes versions de code. En particulier, ils offrent au programmeur des alternatives sur la façon explicite de faire référence à un nom non local.

Source: Un aperçu du langage de programmation C ++ par Bjarne Stroustrup

Rohan Singh
la source
4
Très intéressant qu'une réponse basée sur les conseils d'aucun autre que Bjarne Stroustrup a gagné -2 ... garçon Bjarne devait être un programmeur pauvre et inexpérimenté lorsqu'il a introduit cette fonctionnalité en C ++
nyholku
@nyholku: Voir ça .
sbi
10

Un exemple où using namespace stdgénère une erreur de compilation en raison de l'ambiguïté de count, qui est également une fonction de la bibliothèque d'algorithmes.

#include <iostream>

using namespace std;

int count = 1;
int main() {
    cout << count << endl;
}
Nithin
la source
2
::count--problème résolu. Habituellement, vous aurez plus de choses de l'espace de noms std qu'ailleurs, ergo garder la directive using namespace peut vous éviter de taper.
PSkocik
Le vrai problème ici est que C ++ a toujours des globaux sans espace de noms. Ceci, et le fait que «ceci» est implicite dans les méthodes, cause tellement de bugs et de problèmes que je ne peux même pas les compter, même avec la bonne variable «count». ;)
Aiken Drum
9

Cela n'aggrave pas les performances de votre logiciel ou de votre projet. L'inclusion de l'espace de noms au début de votre code source n'est pas mauvaise. L'inclusion de l' using namespace stdinstruction varie en fonction de vos besoins et de la façon dont vous développez le logiciel ou le projet.

Le namespace stdcontient les fonctions et variables standard C ++. Cet espace de noms est utile lorsque vous utilisez souvent les fonctions standard C ++.

Comme mentionné dans cette page :

L'instruction utilisant l'espace de noms std est généralement considérée comme une mauvaise pratique. L'alternative à cette instruction est de spécifier l'espace de noms auquel l'identifiant appartient en utilisant l'opérateur scope (: :) chaque fois que nous déclarons un type.

Et voyez cet avis :

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 que vous savez avec certitude que rien ne va entrer en collision.

Certaines personnes avaient dit que c'était une mauvaise pratique d'inclure le using namespace stddans vos fichiers source parce que vous appelez à 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 stdvous surchargez la fonction et cela pourrait produire des problèmes dus à la compilation ou à l'exécution. Il ne se compilera pas ou ne s'exécutera pas comme prévu.

Comme mentionné dans cette page :

Bien que l'instruction nous évite de taper std :: chaque fois que nous souhaitons accéder à une classe ou à un type défini dans l'espace de noms std, elle importe l'intégralité de l'espace de noms std dans l'espace de noms actuel du programme. Prenons quelques exemples pour comprendre pourquoi ce n'est peut-être pas une si bonne chose

...

Maintenant, à un stade ultérieur du développement, nous souhaitons utiliser une autre version de cout qui est implémentée sur mesure dans une bibliothèque appelée "foo" (par exemple)

...

Remarquez comment il y a une ambiguïté, vers quelle bibliothèque pointe-t-on? Le compilateur peut détecter cela et ne pas compiler le programme. Dans le pire des cas, le programme peut toujours compiler mais appeler la mauvaise fonction, car nous n'avons jamais spécifié à quel espace de noms l'identifiant appartenait.

CryogenicNeo
la source
7

Je ne pense pas que ce soit 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 de portée avec l'espace de noms pour empêcher votre bibliothèque de buter avec d'autres bibliothèques. Pour le code au niveau de l'application, je ne vois rien de mal à cela.

Dr. Watson
la source
7

"Pourquoi" utiliser l'espace de noms std; " considéré comme une mauvaise pratique en C ++? "

Je l'inverse: pourquoi la saisie de cinq caractères supplémentaires est-elle considérée comme lourde par certains?

Considérez par exemple l'écriture d'un logiciel numérique. Pourquoi envisagerais-je même de polluer mon espace de noms global en coupant "std :: vector" en "vector" alors que "vector" est l'un des concepts les plus importants du domaine problématique?

Solkar
la source
19
Ce n'est pas seulement 5 caractères supplémentaires; ses 5 caractères supplémentaires chaque fois que vous référencez n'importe quel type d'objet dans la bibliothèque standard. Ce qui, si vous utilisez beaucoup la bibliothèque standard, le sera souvent. Il s'agit donc de façon plus réaliste de milliers de caractères supplémentaires dans un programme de taille décente. Vraisemblablement, la directive «using» a été ajoutée au langage afin qu'elle puisse être utilisée ...
Jeremy Friesner
5
Ce n'est pas 5 caractères supplémentaires à chaque fois, c'est 5 caractères et probablement quelques clics de souris pour dérouler un menu et faire une recherche et un remplacement dans l'éditeur de votre choix.
DaveWalley
1
Lisibilité. cout << hex << setw(4) << i << endl;est plus facile à lire questd::cout << std::hex << std::setw(4) << i << std::endl;
oz1cz
16
Et pire encore: std::map<std::string,std::pair<std::string,std::string>>est horrible par rapport à map<string,pair<string,string>>.
oz1cz
4
C'est une bonne pratique de taper vos conteneurs STL de toute façon, donc std :: there n'a pas vraiment d'importance. Et C ++ 11 nous a apporté le mot-clé auto qui rend les choses encore plus faciles lors de l'utilisation, par exemple, d'itérateurs.
juzzlin
7

Je suis d'accord avec les autres - cela demande des affrontements de noms, des ambiguïtés et le fait est que c'est moins explicite. Bien que je puisse voir l'utilisation de using, ma préférence personnelle est de la limiter. Je considérerais également fortement ce que certains ont souligné:

Si vous voulez trouver un nom de fonction qui pourrait être un nom assez courant, mais que vous voulez seulement le trouver dans l' stdespace de noms (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, cela ne me dérange pas vraiment le std::préfixe. J'aime le look plus que de ne pas l'avoir. Je ne sais pas si c'est parce que c'est explicite et me dit "ce n'est pas mon code ... j'utilise la bibliothèque standard" ou si c'est autre chose, mais je pense que c'est plus joli. Cela peut être étrange étant donné que je ne suis entré que récemment dans C ++ (utilisé et continue de faire du C et d'autres langages beaucoup plus longtemps et C est mon langage préféré de tous les temps, juste au-dessus de l'assemblage).

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::namela version et le nom de la bibliothèque standard pour une implémentation spécifique au programme. Oui, en effet, cela pourrait vous mordre et vous mordre fort, mais tout se résume à ce que j'ai commencé ce projet à partir de zéro, et je suis le seul programmeur pour cela. Exemple: je surcharge std::stringet l'appelle string. J'ai des ajouts utiles. Je l'ai fait en partie à cause de ma tendance C et Unix (+ Linux) vers les noms en minuscules.

En plus de cela, vous pouvez avoir des alias d'espace de noms. Voici un exemple où il est utile qui pourrait ne pas avoir été mentionné. J'utilise la norme C ++ 11 et spécifiquement avec libstdc ++. Eh bien, il n'a pas de std::regexsupport complet . Bien sûr, il compile, mais il lève une exception dans le sens où il s'agit d'une erreur de la part du programmeur. Mais c'est le manque de mise en œuvre.

Voici donc comment je l'ai résolu. Installez le regex de Boost et liez-le. Ensuite, je fais ce qui suit pour que lorsque libstdc ++ l'a complètement implémenté, je n'ai besoin que de 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 dirai pas si c'est une mauvaise idée ou non. Je dirai cependant qu'il le garde propre pour mon projet et en même temps le rend spécifique: Vrai, je dois utiliser Boost, mais je l'utilise comme le libstdc ++ l'aura finalement. Oui, démarrer votre propre projet et commencer par une norme (...) au tout début va très loin dans la maintenance, le développement et tout ce qui est impliqué dans le projet!

Juste pour clarifier quelque chose: je ne pense pas que ce soit une bonne idée d'utiliser délibérément et plus spécifiquement le nom d'une classe / quoi que ce soit dans la STL . La chaîne est l'exception (ignorez le premier, ci-dessus ou deuxième ici, jeu de mots si vous devez) pour moi car je n'aimais pas l'idée de «chaîne».

En l'état, je suis toujours très partisan de C et partisan de C ++. Des détails épargnés, une grande partie de ce sur quoi je travaille correspond plus à C (mais c'était un bon exercice et un bon moyen de me faire a. Apprendre une autre langue et b. Essayer de ne pas être moins biaisé contre les objets / classes / etc qui est peut-être mieux énoncé moins fermés, moins arrogants et plus acceptants.). Mais ce qui est utile, c'est ce que certains ont déjà suggéré: j'utilise effectivement list (c'est assez générique, n'est-ce pas?), Et trie (même chose) pour en nommer deux qui provoqueraient un conflit de nom si je le faisais using namespace std;, et ainsi à cette fin, je préfère être spécifique, en contrôle et sachant que si je veux que ce soit l'utilisation standard, je devrai le préciser. En termes simples: aucune supposition autorisée.

Et quant à faire partie des regex de Boost std. Je le fais pour une intégration future et - encore une fois, j'admets pleinement que c'est un parti pris - je ne pense pas que ce soit aussi moche que boost::regex:: .... En effet, c'est autre chose pour moi. Il y a beaucoup de choses en C ++ que je dois encore accepter pleinement dans les looks et les méthodes (un autre exemple: les modèles variadiques contre les arguments var [bien que j'admette que les modèles variadiques soient très très utiles!]). Même ceux que j'accepte, c'était difficile, et j'ai toujours des problèmes avec eux.

Peter Mortensen
la source
1
L'extension de l' stdespace de noms est un comportement non défini et ne doit donc jamais être effectuée.
tambre
7

D'après mon expérience, si vous avez plusieurs bibliothèques qui utilisent disons cout, mais à des fins différentes, vous pouvez utiliser le mauvais cout.

Par exemple, si je tape using namespace std;et using namespace otherlib;et que je tape juste cout(qui se trouve être dans les deux), plutôt que std::cout(ou 'otherlib::cout'), vous pouvez utiliser la mauvaise et obtenir des erreurs. C'est beaucoup plus efficace et efficient à utiliser std::cout.

Dev moteur
la source
6

Avec les identifiants importés non qualifiés, vous avez besoin d'outils de recherche externes comme grep pour savoir où les identifiants sont déclarés. Cela rend le raisonnement sur la correction du programme plus difficile.

August Karlstrom
la source
6

Cela dépend de l'endroit où il se trouve. S'il s'agit d'un en-tête commun, vous diminuez la valeur de l'espace de noms en le fusionnant dans l'espace de noms global. Gardez à l'esprit que cela pourrait être une bonne façon de créer des modules globaux.

MathGladiator
la source
6

Il s'agit d'une mauvaise pratique, souvent appelée pollution globale des espaces de noms. Des problèmes peuvent survenir lorsque plusieurs espaces de noms ont 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 l'espace de noms avec votre appel de fonction comme std::cout. J'espère que cela t'aides. :)

adn.911
la source
5

Pour répondre à votre question, je le vois de cette façon pratiquement: beaucoup de programmeurs (pas tous) invoquent l'espace de noms 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 se trouve dans l'espace de noms std. C'est beaucoup accordé, mais pas tellement par rapport au nombre de mots cohérents et de pseudonymes possibles qui peuvent être proposés à proprement parler.

Je veux dire vraiment ... dire "ne comptez pas sur le fait d'être présent", c'est simplement vous mettre en place pour compter sur le fait qu'il ne soit PAS présent. Vous allez constamment rencontrer des problèmes pour emprunter des extraits de code et les réparer constamment. Gardez simplement vos éléments définis par l'utilisateur et empruntés dans une portée limitée comme ils devraient l'être et soyez TRÈS épargnant avec les globaux (honnêtement, les globaux devraient presque toujours être un dernier recours aux fins de "compiler maintenant, sain d'esprit plus tard"). Vraiment, je pense que c'est un mauvais conseil de votre professeur car utiliser std fonctionnera à la fois pour "cout" et "std :: cout" mais NE PAS utiliser std ne fonctionnera que pour "std :: cout". Vous n'aurez pas toujours la chance d'écrire tout votre code.

REMARQUE: ne vous concentrez pas trop sur les problèmes d'efficacité avant d'avoir réellement appris un peu sur le fonctionnement des compilateurs. Avec un peu d'expérience en codage, vous n'avez pas besoin d'en apprendre beaucoup à leur sujet avant de réaliser à quel point ils sont capables de généraliser un bon code en quelque chose de simple. Tout aussi simple que si vous aviez écrit le tout en C. Un bon code n'est aussi complexe que nécessaire.

Noneyo Getit
la source
Étant donné le nombre de personnes qui semblent ignorer les fonctions de bibliothèque standard utiles (réinventer des choses <algorithm>, par exemple), il semble un peu exagéré d'imaginer que les mêmes personnes pourraient éviter de manière fiable ces identifiants. Parcourez votre propre code et dites-moi que vous n'avez jamais appelé de variable ou de fonction count. Ou distance, ou log, destroy, launch, visit, beta, sample, messages, clamp, erase, copy, modulus, left, etc. Sans parler de tous les identifiants pas encore stdqui va briser votre code lorsque C ++ 35 vient ...
Toby Speight