web-dev-qa-db-fra.com

Pourquoi "using namespace std;" considéré comme une mauvaise pratique?

D'autres personnes m'ont dit qu'écrire using namespace std; dans le code est une erreur et que je devrais plutôt utiliser std::cout et std::cin.

Pourquoi using namespace std; est-il 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'espace de noms std?)? Cela at-il un impact sur les performances?

2409
akbiggs

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

using namespace foo;
using namespace bar;

Tout fonctionne bien, vous pouvez appeler Blah() de Foo et Quux() de Bar sans problèmes. Mais un jour, vous passez à une nouvelle version de Foo 2.0, qui offre maintenant une fonction appelée Quux(). Vous avez maintenant un conflit: Foo 2.0 et Bar importent Quux() dans votre espace de noms global. Cela demandera quelques efforts de réparation, en particulier si les paramètres de la fonction correspondent.

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

2037
Greg Hewgill

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

Library Foo 2.0 pourrait introduire une fonction, Quux(), qui correspond sans équivoque à certains de vos appels à Quux() à celle de bar::Quux() votre code appelé depuis des années. Ensuite, votre code est toujours compilé , mais il appelle silencieusement la mauvaise fonction et fait 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 (pensez list, sort, string, iterator, etc.) qui risquent également d'apparaître dans un autre code.

Si vous considérez cela comme improbable: il y avait ne question a été posée ici sur Stack Overflow où cela s'est produit exactement (fonction incorrecte appelée en raison du préfixe std:: omis) environ un an et demi après avoir donné cette information. répondre. Ici est un autre exemple plus récent d'une telle question. C'est donc un réel problème.


Voici un autre point de données: il y a de nombreuses années, je trouvais aussi ennuyeux de devoir préfixer tout le contenu de la bibliothèque standard avec std::. Ensuite, j'ai travaillé sur un projet dans lequel il était décidé au départ que les deux directives using et les déclarations étaient interdites, à l'exception des portées de fonctions. Devine quoi? Il nous a fallu quelques semaines à la plupart des gens pour s’habituer à l’écriture du préfixe et, au bout de quelques semaines, la plupart d’entre nous ont même convenu qu’il rendait le code plus lisible . Il y a une raison à cela: Que vous préfériez une prose plus courte ou plus longue est subjectif, 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 est référencé.

En une décennie, ce projet a atteint plusieurs millions de lignes de code. Comme ces discussions reviennent encore et encore, j’étais une fois curieux de savoir combien de fois la fonction-scope (autorisée) using était réellement utilisée dans le projet. J'ai grillé les sources pour cela et n'ai trouvé qu'une ou deux douzaines d'endroits où il était utilisé. Pour moi, cela indique que, une fois essayés, les développeurs ne trouvent pas std:: suffisamment pénible pour employer des directives d’utilisation, même une fois par 100 kLoC, même s’il était autorisé à l’utiliser.


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

1300
sbi

Le problème de l'insertion de using namespace dans les fichiers d'en-tête de vos classes est qu'il oblige tous ceux qui le souhaitent (en incluant vos fichiers d'en-tête) à "utiliser" (c'est-à-dire tout voir à l'intérieur) ces autres espaces de noms.

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


Méfiez-vous que certaines personnes ne sont pas d'accord avec mon expression "ne vous sentez pas libre", car ceci bien qu'une instruction using dans un fichier cpp soit meilleure que dans un en-tête ( parce que cela n'affecte pas les personnes qui incluent votre fichier d'en-tête), ils pensent que ce n'est toujours pas bon (car, en fonction du code, cela pourrait rendre l'implémentation de la classe plus difficile à maintenir). Ce FAQ sujet 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 suggère 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:";
    
375
ChrisW

J'ai récemment eu une plainte concernant Visual Studio 201 . Il s’est avéré que pratiquement tous les fichiers source avaient ces deux lignes:

using namespace std;
using namespace boost;

De nombreuses fonctionnalités Boost sont intégrées à la norme C++ 0x et Visual Studio 2010 comporte de nombreuses fonctionnalités C++ 0x; ces programmes ne se sont donc plus compilés.

Par conséquent, éviter using namespace X; est une forme de mise à l'épreuve du temps, une manière de s'assurer qu'une modification apportée aux bibliothèques et/ou aux fichiers d'en-tête utilisés ne va pas casser un programme.

225
David Thornley

Version abrégée: n'utilisez pas global à l'aide de déclarations ou de directives 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 cette question dans Normes de codage C++ (le caractère gras est souligné par moi):

Sommaire

Les utilisations des espaces de noms sont destinées à votre commodité et ne doivent pas être infligées 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; au lieu de cela, explicitement les espaces de noms qualifient tous les noms. (La deuxième règle découle de la première, car les en-têtes ne peuvent jamais savoir quel autre en-tête #includes pourrait apparaître après eux.)

Discussion

En bref: vous pouvez et devez utiliser l'espace de noms en utilisant des déclarations et des directives de manière libérale dans vos fichiers d'implémentation après les directives #include et vous en sentez le sentiment. En dépit des assertions répétées, les espaces de noms utilisant des déclarations et des directives ne sont pas diaboliques et ne vont pas à l'encontre du but des espaces de noms. Ce sont plutôt ce qui rend les espaces de noms utilisables .

203
mattnewport

Il ne faut pas utiliser la directive using au niveau global, en particulier dans les en-têtes. Cependant, il existe des situations où cela convient 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 que la qualification explicite (std::sin, std::cos...) car elle est plus courte et peut fonctionner avec des types à virgule flottante définis par l'utilisateur (via Argument Dependent Lookup).

117
robson3.14

Ne l'utilisez pas globalement

Il est considéré "mauvais" seulement quand tilisé globalement. Parce que:

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

Vous pouvez l'utiliser localement

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

Un idiome pour l'utiliser localement

En C++ 03, il existait un idiome - un code général - pour implémenter une fonction swap pour vos classes. Il a été suggéré que vous utilisiez réellement 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 compilateur choisira le std::swap pour value_, c'est-à-dire void std::swap(int, int).
  • Si vous avez une surcharge void swap(Child&, Child&) implémentée, le compilateur la choisira.
  • Si vous n'avez pas trop de surcharge, le compilateur utilisera void std::swap(Child&,Child&) et tentera de son mieux de les permuter.

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

95
towi

Si vous importez les bons fichiers d’en-tête, vous avez soudain des noms tels que hex , left , plus ou count dans votre étendue globale. Cela peut être surprenant si vous ne savez pas que std:: contient ces noms. Si vous essayez également d'utiliser ces noms localement, vous risquez de créer une certaine confusion.

Si tout le contenu standard se trouve dans son propre espace de noms, vous n'avez pas à vous soucier des conflits de noms avec votre code ou d'autres bibliothèques.

76
sth

Les programmeurs expérimentés utilisent ce qui résout leurs problèmes et évitent tout ce qui crée de nouveaux problèmes, et ils évitent les directives using 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 sources. Une raison mineure à cela est qu’il n’est pas élégant d’écrire plus de code quand moins de code suffit sauf s’il ya de bonnes raisons. Une des principales raisons est la désactivation de la recherche dépendante de l’argument (ADL).

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

Donc, ce qui suit est OK:

  1. Directives et instructions-utilisation au niveau des fonctions dans les implémentations des fonctions
  2. Utilisation de déclarations au niveau du fichier source dans les fichiers source
  3. (Parfois) directives-utilisation au niveau du fichier source
44

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 la normale cout? Est-ce quelque chose de spécial?

43
Martin Beckett

Je conviens 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 explicitement déclarés à cet endroit (y compris les noms déclarés à l'aide de déclarations user telles que His_lib::String) ont priorité sur les noms rendus accessibles dans une autre étendue par une directive using (using namespace Her_lib).

40
Oleksiy

Je considère aussi que c'est une mauvaise pratique. Pourquoi? Un jour, j’ai pensé que la fonction d’un espace de noms consistait à diviser des éléments; je ne devais donc pas gâcher le tout en jetant tout dans un même sac. Cependant, si j'utilise souvent 'cout' et 'cin', j'écris: using std::cout; using std::cin; dans un fichier cpp (jamais dans un fichier d'en-tête car il se propage avec #include). Je pense que personne digne d’esprit ne nommera jamais un flux cout ou cin. ;)

28
Yelonek

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. Ce pourrait être le flux cout de la bibliothèque std. Ou il pourrait y avoir un int cout = 0; dix lignes plus haut dans la même fonction. Ou une variable static nommée cout dans ce fichier. Cela pourrait être n'importe quoi.

Maintenant, prenons un million de codes de lignes, ce qui n’est pas particulièrement grand, et vous recherchez un bogue, ce qui signifie que vous savez qu’une ligne sur un million de lignes ne fait pas ce qu’elle est censée faire. cout << 1; peut lire un static int nommé cout, le décaler d'un bit vers la gauche et jeter le résultat. A la recherche d'un bug, je devrais vérifier ça. Pouvez-vous voir comment je préfère vraiment vraiment voir std::cout?

C’est l’une de ces choses qui semble être une très bonne idée si vous êtes un enseignant et n’avez jamais eu à écrire et à conserver 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 l’écrit savait ce qu’il faisait.

23
gnasher729

Il s'agit de gérer la complexité. En utilisant l’espace de noms, vous obtiendrez des choses que vous ne voudrez pas et rendront probablement plus difficile le débogage (je dis éventuellement). Utiliser std :: partout est plus difficile à lire (plus de texte et tout ça).

Horses for Courses - gérez votre complexité comme vous le pouvez et si vous vous en sentez capable.

22
Preet Sangha
  1. vous devez être capable de lire du code écrit par des personnes qui ont un style différent et des opinions de meilleures pratiques que vous.

  2. Si vous utilisez uniquement cout, personne ne s'embrouille. Mais lorsque vous avez beaucoup d'espaces de noms qui volent autour de vous et que vous voyez cette classe et que vous ne savez pas exactement ce que ça fait, le fait d'avoir un espace de noms explicite se comporte comme un commentaire. Vous pouvez voir à première vue, "oh, ceci est une opération de système de fichiers" ou "c'est faire des trucs de réseau".

18
Dustin Getz

Utiliser plusieurs espaces de noms en même temps est évidemment une recette pour un désastre, mais utiliser JUST namespace std et seul espace de noms std n’est pas un gros problème à mon avis, car la redéfinition ne peut se produire que par votre propre code ...

Il suffit donc de les considérer comme des noms réservés tels que "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 plus d'un à la fois. À moins que ce ne soit le vôtre. Encore une fois, la redéfinition ne se produira pas.

18
user2645752

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 à parcourir pour résoudre 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 éviterez des maux de tête en ne l'utilisant pas dans les fichiers d'en-tête ou dans 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 5 caractères supplémentaires pour clarifier la provenance de mes fonctions.

18
Ron Warholic

Un espace de noms est une portée nommée. Les espaces de noms sont utilisés pour regrouper les déclarations associé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 rédacteurs. 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 constituent 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 manière explicite de faire référence à un nom non local.

Source: Présentation du langage de programmation C++ par Bjarne Stroustrup

12
Rohan Singh

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

Je l'utilise généralement dans ma déclaration de classe, car les méthodes d'une classe ont tendance à traiter avec des types de données similaires (les membres) et un typedef est l'occasion d'attribuer un nom significatif dans le contexte de la classe. Cela facilite réellement 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;
}
12
Carl

Un exemple concret pour clarifier la préoccupation. Imaginez que vous ayez 2 bibliothèques, foo et bar, chacune avec son propre espace de noms:

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

namespace bar {
    ...
}

Maintenant, supposons que vous utilisiez 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, il "fait quelque chose". Mais plus tard, vous mettez à jour la barre et disons que cela a changé pour ressembler à ceci:

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 de la maintenance pour clarifier ce 'a' que vous vouliez dire (c'est-à-dire foo::a). C'est probablement indésirable, mais heureusement, c'est assez facile (ajoutez simplement foo:: devant tous les appels à a que le compilateur marque comme ambigu).

Mais imaginons un scénario alternatif dans lequel bar a plutôt changé pour ressembler à ceci:

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

À ce stade, 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". Aucun avertissement du compilateur ou quoi que ce soit. Votre programme commence silencieusement à faire quelque chose de complètement différent d’avant.

Lorsque vous utilisez un espace de noms, vous vous exposez à un scénario comme celui-ci. C'est pourquoi les personnes ne sont pas à l'aise avec les espaces de noms. Plus le nombre d'éléments présents dans un espace de noms est élevé, plus le risque de conflit est grand. Par conséquent, les utilisateurs risquent d'être encore plus mal à l'aise d'utiliser un espace de noms std (en raison du nombre d'éléments contenus dans cet espace de noms) que d'autres espaces de noms.

En fin de compte, il s’agit d’un compromis entre l’inscriptibilité, la fiabilité et la maintenabilité. La lisibilité peut aussi en tenir compte, mais je pouvais voir les arguments en ce sens. Normalement, je dirais que la fiabilité et la maintenabilité sont plus importantes, mais dans ce cas, vous devrez toujours payer le coût d'écriture pour un impact relativement rare en termes de fiabilité/maintenabilité. Le "meilleur" compromis déterminera votre projet et vos priorités.

11
Kevin

Un exemple où namespace std gé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;
}
9
Nithin

Je ne pense pas que ce soit nécessairement une mauvaise pratique dans toutes les conditions, mais vous devez faire attention lorsque vous l'utilisez. Si vous écrivez une bibliothèque, vous devriez probablement utiliser les opérateurs de résolution d'étendue avec l'espace de noms pour empêcher votre bibliothèque de se heurter à d'autres bibliothèques. Pour le code de niveau d'application, je ne vois rien de mal à cela.

8
Dr. Watson

Cela n'empêche pas les performances de votre logiciel ou de votre projet, l'inclusion de l'espace de nom au début de votre code source n'est pas mauvaise. 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 standard et les variables C++. Cet espace de noms est utile lorsque vous utilisez souvent les fonctions standard C++.

Comme mentionné dans ce page :

L'instruction utilisant namespace 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 appartient l’identifiant à l’aide de l’opérateur scope (: :) à chaque fois que nous déclarons un type.

Et voir cet avis :

Il n’ya aucun problème à utiliser "namespace std" dans votre fichier source lorsque vous utilisez abondamment l’espace de nommage et que vous êtes certain que rien ne va se heurter.

Certaines personnes ont dit qu'il est déconseillé d'inclure le using namespace std dans vos fichiers source, car vous appelez à partir de cet espace de noms toutes les fonctions et variables. Lorsque vous souhaitez définir une nouvelle fonction portant le même nom qu’une autre fonction contenue dans le namespace std, vous surchargez la fonction, ce qui peut entraîner des problèmes de compilation ou d’exécution. Il ne sera pas compilé ou exécuté comme prévu.

Comme mentionné dans ce 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 cela pourrait ne pas être une si bonne chose

...

Maintenant, à un stade ultérieur du développement, nous souhaitons utiliser une autre version de cout personnalisée dans une bibliothèque appelée "foo" (par exemple).

...

Notez qu’il ya une ambiguïté, à quelle bibliothèque c’est pointé par cout? 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 nom appartient l'identificateur.

7
CryogenicNeo

Je suis d’accord avec les autres - c’est demander des conflits 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. J'examinerais aussi fortement ce que d'autres ont souligné:

Si vous voulez trouver un nom de fonction qui pourrait être un nom assez commun, mais que vous voulez seulement le trouver dans l'espace de noms std (ou inversement, vous voulez changer tous les appels qui ne sont PAS dans l'espace de noms std, espace de noms X, ...), comment proposez-vous cela? Vous pouvez é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 plus le look 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 s'il s'agit d'autre chose, mais je pense que c'est plus joli. Cela peut paraître étrange étant donné que je n’ai commencé que récemment à utiliser le langage C++ (je l’utilise et je l’utilise toujours beaucoup plus longtemps, C est mon langage préféré de tous les temps, juste au-dessus de Assembly).

Il y a une autre chose, bien qu'elle soit un 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 standard de la bibliothèque et le nom pour une implémentation spécifique à un 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 que je suis le seul programmeur pour cela. 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 les noms en minuscules.

En plus de cela, vous pouvez avoir des alias d'espace de noms. Voici un exemple de cas où il est utile de ne pas avoir été mentionné. J'utilise le standard C++ 11 et plus particulièrement avec libstdc ++. Eh bien, le support std::regex n’est pas complet. Bien sûr, il compile mais il jette une exception dans le sens où il s’agit d’une erreur commise par le programmeur. Mais c'est un 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, quand libstdc ++ l’a entièrement implémentée, je n’ai plus 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 dirai pas si c'est une mauvaise idée ou non. Je ferai cependant valoir que cela garde la propreté pour mon projet et le rend en même temps spécifique: Vrai, je dois utiliser Boost MAIS je l’utilise comme la libstdc ++ l’aura éventuellement. Oui, démarrer votre propre projet et commencer par une norme (...) au tout début contribue énormément à la maintenance, au développement et à tout ce qui est impliqué dans le projet!

Edit:
Maintenant que j'ai le temps, je tiens à clarifier quelque chose. En fait, je ne pense pas que ce soit une bonne idée d'utiliser un nom de classe/quoi que ce soit dans le TSL délibérément et plus spécifiquement à la place de. La chaîne est l'exception (ignorez le premier, ci-dessus, ou la deuxième ici, jeu de mots si vous le devez) pour moi car je n'aimais pas l'idée de 'String'. En l'état actuel des choses, je suis toujours très biaisé envers le C et biaisé contre le C++. C’est un bon exercice et un bon moyen de me faire apprendre beaucoup de choses, c’est une bonne partie de ce que je travaille qui convient mieux (mais c’est un bon exercice pour apprendre à apprendre une autre langue et b. Essayez de ne pas moins préjuger des objets/classes/etc., ce qui est peut-être mieux indiqué. moins fermés, moins arrogants, plus acceptants). Mais ce qui est utile IS, c’est ce que certains ont déjà suggéré: j’utilise en effet list (c’est assez générique, n’est-ce pas?) using namespace std; et donc à cette fin je préfère être spécifique, en contrôle et en sachant que si je le destine à être l'usage standard alors je devrai le spécifier. En termes simples: aucune hypothèse autorisée.

Et en ce qui concerne l'intégration de l'expression rationnelle de Boost dans std. Je le fais pour une intégration future et - encore une fois, je reconnais pleinement que c'est un parti pris - je ne pense pas que ce soit aussi laid que boost::regex:: ... En effet, c'est autre chose pour moi. Il y a beaucoup de choses en C++ que je n'ai pas encore complètement acceptées dans les styles et les méthodes (un autre exemple: les modèles variadiques par rapport aux arguments variables [même si je reconnais que les modèles variadiques sont très très utiles!]). Même ceux que j’accepte, c’était difficile et j’ai toujours des problèmes avec eux.

6
user4138451

Avec des identificateurs importés non qualifiés, vous avez besoin d'outils de recherche externes tels que grep pour savoir où les identificateurs sont déclarés. Cela rend plus difficile le raisonnement sur l'exactitude du programme.

6
August Karlstrom

C'est une mauvaise pratique, souvent appelée pollution globale par les espaces de noms. Des problèmes peuvent survenir lorsque plusieurs espaces de noms ont le même nom de fonction avec signature. Le compilateur aura alors toute ambiguïté pour 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. :)

6
adn.911

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, cela pourrait être une manière élégante de créer des modules globaux.

6
MathGladiator

"Pourquoi utiliser 'namespace std;' considéré comme une mauvaise pratique en C++? "

Je le répète: pourquoi la saisie de 5 caractères supplémentaires est-elle considérée comme fastidieuse par certains?

Considérons par exemple En écrivant un morceau de logiciel numérique, pourquoi devrais-je même envisager de polluer mon espace de noms global en coupant le "std :: vecteur" général en "vecteur" alors que "vecteur" est l'un des concepts les plus importants du domaine du problème?

6
Solkar

Pour répondre à votre question, j’examine la situation de manière pratique: beaucoup de programmeurs (pas tous) invoquent namespace 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 l’espace de noms std. C’est beaucoup, mais pas tellement comparé au nombre de mots cohérents et de pseudonymes possibles que l’on peut trouver à proprement parler.

Je veux dire vraiment ... dire "ne comptez pas sur sa présence", c'est simplement vous préparer à compter sur elle pour ne PAS être présente. Vous aurez constamment des problèmes pour emprunter des extraits de code et les réparer en permanence. Gardez simplement vos contenus définis et empruntés dans une portée limitée comme ils devraient être et soyez TRÈS économe avec les globals (honnêtement, les globals devraient presque toujours être un dernier recours pour les besoins de "compiler maintenant, santé mentale plus tard"). Vraiment, je pense que votre professeur vous a mal conseillé, car utiliser std fonctionnera à la fois pour "cout" et "std :: cout" mais NE PAS utiliser std ne fonctionnera que pour "std :: cout". Vous ne serez pas toujours assez chanceux pour écrire votre propre code.

REMARQUE: Ne vous concentrez pas trop sur les problèmes d’efficacité jusqu’à ce que vous en apprendrez un peu plus sur le fonctionnement des compilateurs. Avec un peu d'expérience en codage, vous n'avez pas à en apprendre autant sur eux avant de réaliser à quel point ils sont capables de généraliser un bon code en quelque chose de simple. Aussi simple que si vous aviez tout écrit en C. Un bon code est aussi complexe qu'il le faut.

5
Noneyo Getit

D'après mes expériences, si vous avez plusieurs bibliothèques qui utilisent, par exemple, cout, mais dans un but différent, vous pouvez utiliser le mauvais cout.

Par exemple, si je saisis using namespace std; et using namespace otherlib; et que je sais simplement que cout (qui se trouve dans les deux), plutôt que std::cout (ou 'otherlib::cout'), vous pourriez utilisez le mauvais et obtenez des erreurs, il est beaucoup plus efficace d'utiliser std::cout.

5
Engine Dev

Oui, l'espace de noms est important. Une fois dans mon projet, je devais importer une déclaration var dans mon code source, mais lors de sa compilation, elle entrait en conflit avec une autre bibliothèque tierce.

À la fin, j'ai dû contourner le problème par d'autres moyens et rendre le code moins clair.

4
harris

Je pense que l'utilisation de localement ou globalement devrait dépendre de l'application.

Parce que, lorsque nous utilisons la bibliothèque localement, le code peut parfois être un vrai bordel. La lisibilité est faible.

alors, nous devrions utiliser les bibliothèques localement quand il y a seulement une possibilité de conflits.

Je ne suis plus une personne d'expérience. Alors, laissez-moi savoir si je me trompe.

2
meupul

Voici un exemple montrant comment using namespace std; peut conduire à des problèmes de conflit de noms:

Impossible de définir une variable globale en c ++

Dans l'exemple, un nom d'algorithme très générique (std::count) nom entre en conflit avec un nom de variable très raisonnable (count).

2
Martin G

Pour être honnête, pour moi, cela revient à discuter du nombre d'espaces pour l'indentation. L'utilisation de directives dans les en-têtes cause des dommages. Mais dans les fichiers c ++? Peut-être si vous utilisez 2 espaces de noms à la fois. Mais si vous en utilisez un, c'est plus une question de style que d'efficacité réelle. Savez-vous pourquoi les discussions sur l'indentation sont si populaires? Tout le monde peut en dire quelque chose et avoir l’air très intelligent et expérimenté.

1
Timon Paßlick

C'est au cas par cas. Nous voulons minimiser le "coût total de possession" du logiciel sur toute sa durée de vie. La déclaration "using namespace std" a certains coûts, mais pas son utilisation a également un coût en lisibilité.

Les gens soulignent à juste titre que lors de son utilisation, lorsque la bibliothèque std introduit de nouveaux symboles et définitions, votre code cesse de se compiler et vous pouvez être obligé de renommer des variables. Et pourtant, c'est probablement une bonne chose à long terme, car les futurs responsables de la maintenance seront momentanément confus ou distraits si vous utilisez un mot clé à des fins surprenantes. Vous ne voulez pas avoir un modèle appelé vecteur, disons, qui n'est pas le vecteur connu de tous les autres. Et le nombre de nouvelles définitions ainsi introduites dans la bibliothèque C++ est suffisamment petit pour ne pas apparaître. Il y a un coût pour avoir à faire ce genre de changement, mais le coût n'est pas élevé et est compensé par la clarté gagnée en n'utilisant pas de noms de symboles std à d'autres fins.

Étant donné le nombre de classes, de variables et de fonctions, énoncer std :: on le ferait sur votre code, ce qui aurait pour effet de gonfler votre code de 50% et compliquerait la tâche. Un algorithme ou une étape dans une méthode qui pourrait être intégrée à un écran de code nécessite maintenant un défilement en avant et en aval. C'est un coût réel. On peut soutenir que cela ne représente pas un coût élevé, mais les personnes qui nient l'existence de celui-ci sont inexpérimentées, dogmatiques ou ont tout simplement tort.

J'offrirais les règles suivantes:

  1. std est différent de toutes les autres bibliothèques. C'est la bibliothèque que tout le monde a besoin de savoir, et à mon avis, il vaut mieux penser à faire partie du langage. D'une manière générale, il existe un excellent cas pour using namespace std même s'il n'y en a pas pour d'autres bibliothèques.

  2. Ne forcez jamais la décision sur l'auteur d'une unité de compilation (un fichier .cpp) en le mettant dans un en-tête. Toujours reporter la décision à l'auteur de l'unité de compilation. Même dans un projet qui a décidé d'utiliser using namespace std partout, vous risquez de perdre quelques modules qui sont mieux gérés comme des exceptions à cette règle.

  3. Bien que la fonctionnalité d'espace de noms vous permette d'avoir de nombreux modules avec des symboles définis de la même manière, cela risque d'être déroutant. Gardez les noms différents dans la mesure du possible. Même si vous n'utilisez pas la fonction d'espace de noms, si vous avez une classe nommée foo et que std introduit une classe nommée foo, il est probablement préférable à long terme de renommer votre classe.

  4. Une alternative à l'utilisation des espaces de noms consiste à manuellement les symboles d'espace de noms en les préfixant. J'ai deux bibliothèques que j'ai utilisées pendant des décennies, les deux commençant par les bibliothèques C, en fait, où chaque symbole est précédé de "AK" ou "SCWin" . En règle générale, cela revient à éviter la construction "using", mais vous n'écrivez pas les deux points. AK :: foo () est à la place de AKFoo (). Cela rend le code 5-10% plus dense et moins bavard, et le seul inconvénient est que vous aurez de gros problèmes si vous devez utiliser deux de ces bibliothèques avec le même préfixe. Notez que les bibliothèques X-Windows sont excellentes à cet égard, sauf qu’elles ont oublié de le faire avec quelques #defines: TRUE et FALSE auraient dû être XTRUE et XFALSE, ce qui a créé un conflit d’espace de nommage avec Sybase ou Oracle qui utilisait également TRUE et FAUX avec des valeurs différentes! (ASCII 0 et 1 dans le cas de la base de données!) Un avantage particulier est qu’elle s’applique sans faille aux définitions de pré-processeur, alors que le système C++ utilisant/namespace ne les gère pas. L’un des avantages intéressants de cette solution est qu’elle donne une pente organique qui fait partie d’un projet et qui finit par devenir une bibliothèque. Dans une grande application, toutes les classes de fenêtres portent le préfixe Win, tous les modules de traitement du signal Mod, etc. Il est donc peu probable que ces éléments soient réutilisés. Il n’ya donc aucun avantage pratique à transformer chaque groupe en une bibliothèque, mais il est évident en quelques secondes que le projet se divise en sous-projets.

1
Swiss Frank

Voici un point de vue que je n'ai trouvé dans aucune des réponses: n'utilisez qu'un seul espace de noms. Selon la plupart des réponses, la principale raison pour laquelle les espaces de noms sont défectueux est que vous pouvez avoir des noms de fonction en conflit pouvant entraîner un désordre total. Toutefois, cela ne se produira pas si vous utilisez un seul espace de noms. Choisissez la bibliothèque que vous utiliserez le plus (peut-être using namespace std;) et respectez-la.

On peut penser qu’il a un préfixe de bibliothèque invisible - std::vector devient simplement vector. Ceci, à mon avis, est le meilleur des deux mondes: d’une part, cela réduit le nombre de saisies que vous devez faire (comme prévu par les espaces de noms) et, d’autre part, vous devez toujours utiliser les préfixes pour plus de clarté et de sécurité. S'il existe une fonction ou un objet sans préfixe d'espace de nom, vous savez que cela provient de l'espace de nom que vous avez déclaré.

Rappelez-vous simplement que si vous décidez d’en utiliser un au niveau mondial, n’en utilisez pas d’autres localement. Cela nous ramène aux autres réponses, à savoir que les espaces de noms locaux sont souvent plus utiles que les espaces globaux car ils offrent une grande variété de commodités.

1
m_highlanderish