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?
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
, iterator
etc.), 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.
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.
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.
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)).
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