Warum ist “using namespace std;” als schlechte Praxis angesehen?

Lesezeit: 5 Minuten

Warum ist using namespace std als schlechte Praxis angesehen
akbiggs

Mir wurde von anderen gesagt, dass das Schreiben using namespace std; im Code ist falsch, und das sollte ich verwenden std::cout und std::cin stattdessen direkt.

Warum ist using namespace std; als schlechte Praxis angesehen? Ist es ineffizient oder riskiert es, mehrdeutige Variablen zu deklarieren (Variablen, die den gleichen Namen haben wie eine Funktion in std Namensraum)? Beeinflusst es die Leistung?

  • Vergessen Sie nicht, dass Sie Folgendes tun können: “using std::cout;” was bedeutet, dass Sie nicht std::cout eingeben müssen, aber nicht den gesamten std-Namespace gleichzeitig einbringen müssen.

    – Rechnung

    21. September 2009 um 15:29 Uhr

  • Es ist besonders schlecht, ‘using namespace std’ im Dateibereich in Header-Dateien zu verwenden. Die Verwendung in Quelldateien (*.cpp) im Dateibereich ist schließlich nicht ganz so schlimm, da seine Wirkung auf eine einzelne Übersetzungseinheit beschränkt ist. Noch weniger problematisch ist die Verwendung innerhalb von Funktionen oder Klassen, da seine Wirkung auf den Funktions- oder Klassenbereich beschränkt ist.

    – Sch-

    25. Juni 2017 um 14:37 Uhr

  • Ich würde davon abraten, die using-Direktive zu verwenden, aber für bestimmte Namespaces wie std::literals::chrono_literals, Poco::Data:Keywords,Poco::Units und Dinge, die sich mit Literalen oder Lesbarkeitstricks befassen. Wann immer es sich in Header- oder Implementierungsdateien befindet. Es könnte in einem Funktionsumfang in Ordnung sein, denke ich, aber abgesehen von Literalen und anderem Zeug ist es nicht nützlich.

    – Ludovic Zenohate Lagouardette

    19. Juli 2017 um 9:33 Uhr

  • @Jon: Es hat insbesondere nichts mit Namespace std zu tun. Meine Betonung sollte auf “im Dateibereich in Header-Dateien” liegen. Um es als Ratschlag auszudrücken: Verwenden Sie nicht “using namespace” (std oder andere) im Dateibereich in Header-Dateien. Es ist in Ordnung, es in Implementierungsdateien zu verwenden. Sorry für die Zweideutigkeit.

    – Sch-

    9. April 2018 um 14:10 Uhr

  • Es wird nur in Kopfzeilen als schlechte Praxis angesehen. Es ist in Ordnung in Quelldateien, die nicht anderswo enthalten sind (dh cpp-Dateien). Siehe die Antwort von @mattnewport unten. stackoverflow.com/a/26722134/125997

    – Danra

    11. August 2019 um 10:55 Uhr

1647320419 550 Warum ist using namespace std als schlechte Praxis angesehen
sbi

Ich stimme allem zu, was Greg geschrieben hat, aber ich möchte hinzufügen: Es kann sogar noch schlimmer werden, als Greg gesagt hat!

Library Foo 2.0 könnte eine Funktion einführen, Quux()das ist eindeutig besser für einige Ihrer Anrufe geeignet Quux() als das bar::Quux() Dein Code rief jahrelang an. Dann deine Code wird immer noch kompiliertaber es ruft stillschweigend die falsche Funktion auf und tut Gott weiß was. Das ist ungefähr das Schlimmste, was es geben kann.

Denken Sie daran, dass die std Namespace hat Tonnen von Bezeichnern, von denen viele sind sehr gemeinsame (denke list, sort, string, iteratoretc.), die sehr wahrscheinlich auch in anderem Code vorkommen.

Wenn Sie dies für unwahrscheinlich halten: Es wurde eine Frage hier auf Stack Overflow gestellt, wo ziemlich genau dies passiert ist (falsche Funktion aufgerufen, weil weggelassen std:: Präfix) etwa ein halbes Jahr, nachdem ich diese Antwort gegeben hatte. Hier ist ein weiteres, neueres Beispiel für eine solche Frage. Das ist also ein echtes Problem.


Hier noch ein Datenpunkt: Vor vielen, vielen Jahren fand ich es auch lästig, alles aus der Standardbibliothek mit voranstellen zu müssen std::. Dann habe ich in einem Projekt gearbeitet, wo am Anfang entschieden wurde, dass beides using Direktiven und Deklarationen sind mit Ausnahme von Funktionsbereichen verboten. Erraten Sie, was? Die meisten von uns brauchten nur wenige Wochen, um sich an das Schreiben des Präfixes zu gewöhnen, und nach ein paar weiteren Wochen waren sich die meisten von uns sogar einig, dass es tatsächlich den Code erstellte besser lesbar. Dafür gibt es einen Grund: Ob Sie kürzere oder längere Prosa mögen, ist subjektiv, aber die Präfixe verleihen dem Code objektiv Klarheit. Nicht nur der Compiler, sondern auch Sie können leichter erkennen, auf welchen Bezeichner verwiesen wird.

Innerhalb eines Jahrzehnts wuchs dieses Projekt auf mehrere Millionen Codezeilen an. Da diese Diskussionen immer wieder auftauchen, war ich mal gespannt wie oft der (erlaubte) Funktionsumfang ist using tatsächlich in dem Projekt verwendet wurde. Ich habe die Quellen dafür durchsucht und nur ein oder zwei Dutzend Stellen gefunden, an denen es verwendet wurde. Für mich weist dies darauf hin, dass Entwickler, wenn sie es einmal versucht haben, nicht finden std:: schmerzhaft genug, um using-Anweisungen sogar einmal alle 100 kLoC anzuwenden, selbst wenn es erlaubt war, verwendet zu werden.


Fazit: Alles explizit voranzustellen schadet nicht, ist wenig gewöhnungsbedürftig und hat objektive Vorteile. Insbesondere erleichtert es die Interpretation des Codes durch den Compiler und durch menschliche Leser – und das sollte wahrscheinlich das Hauptziel beim Schreiben von Code sein.

  • Uneinigkeit über die Interpretation durch den Leser, da foo::bar() eine Funktionsleiste aus dem Namensraum foo oder eine statische Funktion aus der Klasse foo bedeuten kann.

    – Konvertieren

    9. Februar um 21:15 Uhr

  • @convert Und warum sollte jemand eine Klasse anrufen foo anstatt Foo? Und statische Methoden sollten auch aufgerufen werden Foo::Bar und nicht Foo::bar. Deshalb dachten die Leute, dass Konventionen eine gute Sache sind.

    – Stefan Riedel

    14. Februar um 11:20 Uhr

  • @Stefan Riedel Weiß nicht, aber es ist gängige Praxis in C++. Zum Beispiel ist es String und Vektor und nicht String und Vektor.

    – Konvertieren

    14. Februar um 11:41 Uhr

  • @convert ist in der Standardbibliothek üblich. Die meisten (alle mir bekannten) C++-Codierungskonventionen empfehlen großgeschriebene Klassen. Mehr als die Hälfte der Konventionen, die ich kenne, empfehlen großgeschriebene statische Methoden. Und selbst wenn Sie eine Voodoo-Codierungskonvention haben, die beides nicht tut, haben foo::bar als statisches Verfahren spricht dennoch kein Argument gegen die Interpretation. Es ist noch klarer, wo diese Funktion/Methode hingehört und wenn Sie Ihrer Klasse einen guten Namen geben, ist es immer noch klar, dass eine Klasse gemeint ist und kein Namespace.

    – Stefan Riedel

    14. Februar um 13:04 Uhr

  • @Stefan Riedel In meinem Beispiel ging es um Klassen aus ANSI C++ wie String und Vektor. Sie sagen also ANSI C++ mit einer Voodoo-Codierungskonvention?

    – Konvertieren

    14. Februar um 13:42 Uhr

  • Natürlich sollten Sie auch niemals den Zustand des globalen cout annehmen, damit nicht jemand std:cout << std::hex hat und danach std::restore_cout_state nicht ausgeführt hat. Aber das ist ein ganz anderer Fettberg.

    – Móż

    2. November 2019 um 9:13 Uhr

  • “Sie können jedoch gerne eine using-Anweisung in Ihre (privaten) *.cpp-Dateien einfügen.” Und was ist, wenn ein zukünftiges Entwicklerteam beschließt, das Übersetzungseinheitenschema zu ändern, beispielsweise über UnityBuilds? Im Zweifel werden Sie mit schrecklichem undefiniertem Verhalten enden.

    – Sekundi

    16. Dezember 2020 um 14:05 Uhr

  • Während die Bedenken in Bezug auf Header-Dateien berechtigt sein können, aufgrund der Art und Weise, wie Includes Nebenwirkungen haben können, habe ich das Gefühl, dass dies nicht im Fall von cpp-Dateien der Fall ist. Schauen wir uns an, was in praktisch jeder anderen Programmiersprache passiert. Wenn Sie zB in Java programmieren, importieren Sie fast immer jedes Symbol aus den von Ihnen verwendeten Paketen – insbesondere aus den Standardpaketen. Das bedeutet, dass Sie fast nie eine konkurrierende und widersprüchliche Implementierung von String, List, Map usw. erwarten. Dasselbe gilt für andere Sprachen, die ich kenne. Es ist meiner Meinung nach vernünftig und wir sollten das Leben einfach und nicht schwer machen.

    – Dimitrios Menounos

    21. Dezember 2020 um 15:51 Uhr

  • Wenn ein Team zu Unity Build migriert, muss es using-Schlüsselwörter entfernen und weinen, weil die Verwendung von stdlib ohne using mühsam ist. Wenn Sie sich jedoch auf Qt verlassen, ist dies in Ordnung, da Qt keinen Namensraum verwendet (segne sie). Dennoch ist Unity Builds ein Grenzfall.

    – Kiruahxh

    10. März 2021 um 16:18 Uhr

  • …für dich. Für die überwiegende Mehrheit des C++-Ökosystems, einschließlich des C++-Komitees, ist dies jedoch nicht nur eine Option, sondern auch die empfohlene.

    – Spektren

    9. April 2021 um 11:22 Uhr


1647320420 598 Warum ist using namespace std als schlechte Praxis angesehen
David Thornley

Ich bin kürzlich auf eine Beschwerde gestoßen Visual Studio 2010. Es stellte sich heraus, dass so ziemlich alle Quelldateien diese beiden Zeilen hatten:

using namespace std;
using namespace boost;

Viel Schub Features werden in den C++0x-Standard aufgenommen, und Visual Studio 2010 verfügt über viele C++0x-Features, sodass diese Programme plötzlich nicht mehr kompiliert werden konnten.

Daher vermeiden using namespace X; ist eine Form der Zukunftssicherheit, eine Möglichkeit sicherzustellen, dass eine Änderung an den verwendeten Bibliotheken und/oder Header-Dateien ein Programm nicht beschädigt.

  • Dies. Boost und std haben a viel von Überschneidungen – insbesondere seit C++11.

    – einpoklum

    24. Februar 2016 um 16:40 Uhr

  • Ich habe das einmal gemacht und eine Lektion auf die harte Tour gelernt. Jetzt benutze ich nie using außerhalb einer Funktionsdefinition und werden selten verwendet using namespace überhaupt.

    – Ferruccio

    10. April 2018 um 13:45 Uhr

  • Ich persönlich würde Boost niemals verwenden, da es die schlechteste C++ API ist, die ich je gesehen habe. Welche Probleme könnte ich dann noch haben, wenn ich namespace std verwende?

    – Konvertieren

    9. Februar um 21:21 Uhr

1647320420 397 Warum ist using namespace std als schlechte Praxis angesehen
Gemeinschaft

Kurzversion: Verwenden Sie nicht global using Deklarationen oder Direktiven in Header-Dateien. Fühlen Sie sich frei, sie in Implementierungsdateien zu verwenden. Hier ist was Herb Sutter und Andrej Alexandrescu zu diesem Problem in den C++-Codierungsstandards zu sagen (Fettdruck zur Hervorhebung stammt von mir):

Zusammenfassung

Namensraum-Usings sind für Ihre Bequemlichkeit, nicht für Sie, um sie anderen aufzuerlegen: Schreiben Sie niemals eine using-Deklaration oder eine using-Direktive vor eine #include-Direktive.

Folgerung: Schreiben Sie in Header-Dateien keine Direktiven oder Deklarationen auf Namespace-Ebene; qualifizieren Sie stattdessen explizit alle Namen für den Namensraum. (Die zweite Regel folgt aus der ersten, da Header nie wissen können, welche anderen Header #includes nach ihnen erscheinen könnten.)

Diskussion

Kurz gesagt: Sie können und sollten Namensräume mit Deklarationen und Direktiven großzügig in Ihren Implementierungsdateien nach #include-Direktiven verwenden und sich dabei gut fühlen. Trotz wiederholter gegenteiliger Behauptungen sind Namensräume, die Deklarationen und Direktiven verwenden, nicht böse und sie machen den Zweck von Namensräumen nicht zunichte. Vielmehr machen sie Namespaces nutzbar.

  • Dies. Boost und std haben a viel von Überschneidungen – insbesondere seit C++11.

    – einpoklum

    24. Februar 2016 um 16:40 Uhr

  • Ich habe das einmal gemacht und eine Lektion auf die harte Tour gelernt. Jetzt benutze ich nie using außerhalb einer Funktionsdefinition und werden selten verwendet using namespace überhaupt.

    – Ferruccio

    10. April 2018 um 13:45 Uhr

  • Ich persönlich würde Boost niemals verwenden, da es die schlechteste C++ API ist, die ich je gesehen habe. Welche Probleme könnte ich dann noch haben, wenn ich namespace std verwende?

    – Konvertieren

    9. Februar um 21:21 Uhr

1647320421 987 Warum ist using namespace std als schlechte Praxis angesehen
Peter Mortensen

Die sollte man nicht verwenden using Direktive im globalen Bereich, insbesondere in Headern. Es gibt jedoch Situationen, in denen es sogar in einer Header-Datei angebracht ist:

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));
}

Dies ist besser als eine explizite Qualifizierung (std::sin, std::cos…), weil es kürzer ist und mit benutzerdefinierten Fließkommatypen arbeiten kann (via argumentabhängige Suche (ADL)).

  • @Billy: Es gibt keine andere Möglichkeit, den Aufruf von userlib::cos(userlib::superint) zu unterstützen. Jede Funktion hat einen Nutzen.

    – Zan Luchs

    24. Juni 2011 um 23:42 Uhr

  • @Zan: Natürlich gibt es das. using std::cos; , using std::sinusw. Das Problem ist jedoch, dass alle gut gestaltet sind userlib wird ihre haben sin und cos auch innerhalb ihres eigenen Namensraums, also hilft Ihnen das wirklich nicht weiter. (Außer es gibt eine using namespace userlib vor dieser Vorlage und das ist genauso schlimm wie using namespace std — und der Umfang dort ist nicht begrenzt.) Außerdem ist die einzige Funktion wie diese, die mir jemals passiert ist swapund in solchen Fällen würde ich empfehlen, einfach eine Vorlagenspezialisierung von zu erstellen std::swap und Vermeidung des ganzen Problems.

    – Billy ONeal

    24. Juni 2011 um 23:48 Uhr

  • @BillyONeal: template<typename T> void swap(MyContainer<T>&, MyContainer<T>&) (Es gibt keine partielle Spezialisierung von Funktionsvorlagen (FTPS), daher müssen Sie manchmal stattdessen auf Überladen zurückgreifen.

    – sbi

    30. Mai 2012 um 14:56 Uhr


  • @BillyONeal: Dein (7-fach positiver!) Kommentar ist falsch – die Situation, die du beschreibst, ist falsch exakt wofür ADL entwickelt wurde. Kurz, wenn x hat einen oder mehrere “zugehörige Namensräume” (z. B. wenn es in definiert wurde namespace userlib) dann jeder Funktionsaufruf, der aussieht cos(x) Wille zusätzlich Schauen Sie in diesen Namensräumen nach — ohne irgendein using namespace userlib; vorher notwendig. Zan Lynx hat Recht (und die Namenssuche in C++ ist byzantinisch …)

    – j_random_hacker

    4. September 2015 um 15:31 Uhr

  • Anstatt using namespace std;Ich würde bevorzugen using std::sin; using std::cos; using std::exp;. Sie erhalten den gleichen Vorteil ohne Dumping-Risiken std::* in eine Funktion.

    – Ferruccio

    10. Mai 2016 um 22:18 Uhr

1004000cookie-checkWarum ist “using namespace std;” als schlechte Praxis angesehen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy