Ich habe von anderen gesagt , dass das Schreiben using namespace std;
in Code falsch ist, und dass ich verwenden sollte std::cout
und std::cin
stattdessen direkt.
Warum wird dies using namespace std;
als schlechte Praxis angesehen? Ist es ineffizient oder besteht die Gefahr, dass mehrdeutige Variablen deklariert werden (Variablen, die denselben Namen wie eine Funktion im std
Namespace haben)? Beeinträchtigt es die Leistung?
c++
namespaces
std
using-directives
c++-faq
akbiggs
quelle
quelle
std::literals::chrono_literals
,Poco::Data:Keywords
,Poco::Units
und Sachen , die mit Literalen oder Lesbarkeit Tricks beschäftigen. Wann immer es in Header- oder Implementierungsdateien ist. Es mag in einem Funktionsumfang in Ordnung sein, aber abgesehen von Literalen und anderen Dingen ist es nicht nützlich.Antworten:
Dies hängt überhaupt nicht mit der Leistung zusammen. Beachten Sie jedoch Folgendes: Sie verwenden zwei Bibliotheken mit den Namen Foo und Bar:
Alles funktioniert gut und Sie können problemlos
Blah()
von Foo undQuux()
Bar anrufen . Aber eines Tages aktualisieren Sie auf eine neue Version von Foo 2.0, die jetzt eine Funktion namens bietetQuux()
. Jetzt haben Sie einen Konflikt: Sowohl Foo 2.0 als auch Bar werdenQuux()
in Ihren globalen Namespace importiert . Die Behebung dieses Problems erfordert einige Anstrengungen, insbesondere wenn die Funktionsparameter übereinstimmen.Wenn Sie
foo::Blah()
und verwendet hättenbar::Quux()
,foo::Quux()
wäre die Einführung von kein Ereignis gewesen.quelle
#define
ist, dass es sich nicht auf Namespaces beschränkt, sondern über die gesamte Codebasis trampelt. Ein Namespace-Alias ist das, was Sie wollen.Ich stimme allem zu, was Greg geschrieben hat , aber ich möchte hinzufügen: Es kann noch schlimmer werden, als Greg gesagt hat!
Library Foo 2.0 könnte eine Funktion einführen
Quux()
, die für einige Ihrer Aufrufe eindeutig besser passtQuux()
als derbar::Quux()
Code, den Sie seit Jahren aufgerufen haben. Dann wird Ihr Code immer noch kompiliert , aber er ruft stillschweigend die falsche Funktion auf und macht Gott-weiß-was. Das ist ungefähr so schlimm, wie es nur geht.Beachten Sie, dass der
std
Namespace - Tonnen - Kennungen hat, von denen viele sehr gewöhnlichsten (denkenlist
,sort
,string
,iterator
etc.) , die sehr wahrscheinlich in anderen Code erscheinen, zu.Wenn Sie dies für unwahrscheinlich halten: Hier auf Stack Overflow wurde eine Frage gestellt, bei der genau
std::
ein halbes Jahr, nachdem ich diese Antwort gegeben habe, ziemlich genau dies passiert ist (falsche Funktion wird aufgrund des ausgelassenen Präfixes aufgerufen ). 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 ärgerlich, alles aus der Standardbibliothek voranstellen zu müssen
std::
. Dann habe ich in einem Projekt gearbeitet, in dem zu Beginn entschieden wurde, dass sowohlusing
Direktiven als auch Deklarationen mit Ausnahme von Funktionsbereichen verboten sind. Erraten Sie, was? Die meisten von uns brauchten sehr wenige Wochen, um sich an das Schreiben des Präfixes zu gewöhnen, und nach einigen weiteren Wochen waren sich die meisten sogar einig, dass der Code dadurch besser lesbar wurde . 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.In einem Jahrzehnt wuchs dieses Projekt auf mehrere Millionen Codezeilen. Da diese Diskussionen immer wieder auftauchen, war ich einmal gespannt, wie oft der (erlaubte) Funktionsumfang
using
tatsächlich im Projekt verwendet wurde. Ich suchte nach den Quellen dafür und fand nur ein oder zwei Dutzend Stellen, an denen es verwendet wurde. Für mich bedeutet dies, dass Entwickler nach dem Versuch nichtstd::
schmerzhaft genug sind, um Direktiven auch nur einmal alle 100 kLoC zu verwenden, selbst wenn sie verwendet werden durften.Fazit: Das explizite Präfixieren von allem schadet nicht, ist sehr gewöhnungsbedürftig und hat objektive Vorteile. Insbesondere erleichtert dies die Interpretation des Codes durch den Compiler und durch menschliche Leser - und dies sollte wahrscheinlich das Hauptziel beim Schreiben von Code sein.
quelle
string
, und anscheinend hatte jede Bibliothek ihre eigene. Sagen Sie was: Wir werden unseren Code weiter schreibenstd::
, und Sie können unseren Code durchlaufen,grep -v std:: | vim
wenn Sie ihn durchsuchen. Oder Sie können Ihrem Editor beibringen, dassstd::
es sich um ein Schlüsselwort handelt, das genauso wie die Hintergrundfarbe gefärbt werden soll. Was auch immer funktioniert.std::
es überhaupt schädlich ist. Es enthält sehr wichtige Informationen (nämlich "was auch immer danach kommt, ist Teil der Standardbibliothek", und es ist immer noch ein ziemlich kurzes und kompaktes Präfix. Meistens ist es überhaupt kein Problem. Manchmal haben Sie ein paar Codezeilen wo Sie bestimmen Symbole in der verweisen müssenstd
vielen Namensraum, und dann einusing
. das Problem schön Aussage in dieser besonderen Rahmen löst aber im allgemeinen Fall ist es nicht Lärm, vermittelt es wertvolle Informationen zusätzlich zu entfernen Zweideutigkeiten.std::
, weiß ich, dass es von kommen wird,std::
ohne darüber nachdenken zu müssen. Wenn ichstring
oderlist
odermap
alleine sehe, frage ich mich ein bisschen.vector
,transform
oderdistance
. Und das sind nur Beispiele für die vielen, sehr gebräuchlichen Namen, die in der Standardbibliothek verwendet werden. Es ist eher kontraproduktiv, sie nicht aus Angst oder aus einer voreingenommenen Meinung über die Namespace-Funktion zu verwenden, die ein wesentlicher Bestandteil von C ++ ist.Das Problem beim Einfügen
using namespace
der Header-Dateien Ihrer Klassen besteht darin, dass jeder, der Ihre Klassen verwenden möchte (indem er Ihre Header-Dateien einbezieht), auch diese anderen Namespaces "verwendet" (dh alles darin sieht).Sie können jedoch auch eine using-Anweisung in Ihre (privaten) * .cpp-Dateien einfügen.
Beachten Sie, dass einige Leute mit meinem Sprichwort "Fühlen Sie sich frei" nicht einverstanden sind - denn obwohl a
using
Aussage in einer CPP-Datei besser ist als in einem Header (weil sie keine Auswirkungen auf Personen hat, die Ihre Header-Datei enthalten), denken sie, dass dies immer noch nicht der Fall ist gut (weil es je nach Code die Wartung der Klasse schwieriger machen könnte). Dieser C ++ Super-FAQ-Eintrag sagt:Die FAQ schlägt zwei Alternativen vor:
Eine using-Erklärung:
Geben Sie einfach std :: ein
quelle
Ich bin kürzlich auf eine Beschwerde über Visual Studio 2010 gestoßen . Es stellte sich heraus, dass so ziemlich alle Quelldateien diese beiden Zeilen hatten:
Viel Boost Funktionen werden in den C ++ 0x-Standard aufgenommen, und Visual Studio 2010 verfügt über viele C ++ 0x-Funktionen, sodass diese Programme plötzlich nicht mehr kompiliert wurden.
Vermeiden
using namespace X;
ist daher eine Form der Zukunftssicherheit, um sicherzustellen, dass eine Änderung der verwendeten Bibliotheken und / oder Header-Dateien ein Programm nicht beschädigt.quelle
using
außerhalb einer Funktionsdefinition undusing namespace
überhaupt nicht mehr.Kurzversion: Verwenden Sie keine globalen
using
Deklarationen oder Anweisungen in Header-Dateien. Fühlen Sie sich frei, sie in Implementierungsdateien zu verwenden. Hier ist, was Herb Sutter und Andrei Alexandrescu zu diesem Thema in C ++ Coding Standards zu sagen haben (Fettdruck für die Betonung liegt bei mir):quelle
using
niemals in einem Header erscheinen sollte, zu 100% zustimme , bin ich nicht so überzeugt von der kostenlosen Lizenz,using namespace xyz;
irgendwo in Ihrem Code zu platzieren, besonders wenn dies der Fallxyz
iststd
. Ich verwende dasusing std::vector;
Formular, da dadurch nur ein einzelnes Element aus dem Namespace in den pseudo-globalen Bereich gezogen wird, was zu einem weitaus geringeren Kollisionsrisiko führt.using namespace
es böse ist, wiegoto
es böse ist. Beide haben gültige Verwendungen, aber 999 von 1000 werden sie falsch verwendet. Also, ja, mitusing namespace
in der Quelle werden Sie den Namespace anderer Includes nicht verschmutzen, ordentlich. Aber es schützt dich immer noch nicht vor dem "Spaß" , der entsteht, wennusing namespace Foo
+using namespace Bar
du anrufst (implizites Foo: :)baz(xyz)
und plötzlich der Code bricht (ohne verwandte Änderungen), nur weil erBar::baz()
irgendwo hinzugefügt wurde, was einfach besser ist Match (und wird jetzt stattdessen aufgerufen)Man sollte die
using
Direktive nicht im globalen Bereich verwenden, insbesondere in Headern. Es gibt jedoch Situationen, in denen dies auch in einer Header-Datei angemessen ist:Dies ist besser als die explizite Qualifizierung (
std::sin
,std::cos
...), da sie kürzer ist und mit benutzerdefinierten Gleitkommatypen (über argumentabhängige Suche (ADL)) arbeiten kann.quelle
using std::cos;
,using std::sin
Obwohl usw. Das Problem ist , dass jeder gut gestaltetuserlib
wird sie habensin
undcos
in ihrem eigenen Namensraum als auch, so die wirklich helfen Ihnen nicht. (Es sei denn, es gibt eineusing namespace userlib
vor dieser Vorlage und das ist genauso schlecht wieusing namespace std
- und der Umfang dort ist nicht begrenzt.) Außerdem ist die einzige Funktion wie diese, die mir jemals passiertswap
, und in solchen Fällen würde ich empfehlen, nur eine Vorlage zu erstellen Spezialisierungstd::swap
und Vermeidung des gesamten Problems.template<typename T> void swap(MyContainer<T>&, MyContainer<T>&)
(Es gibt keine partielle Spezialisierung für Funktionsvorlagen (FTPS), daher müssen Sie manchmal stattdessen auf Überlastung zurückgreifen.x
ein oder mehrere "zugeordnete Namespaces" vorhanden sind (z. B. wenn er in definiert wurdenamespace userlib
), wird jeder Funktionsaufruf, der so aussiehtcos(x)
, zusätzlich in diesen Namespaces angezeigt - ohne dass diesusing namespace userlib;
zuvor erforderlich ist. Zan Lynx hat recht (und die Suche nach C ++ - Namen ist byzantinisch ...)Verwenden Sie es nicht global
Es wird nur dann als "schlecht" angesehen, wenn es global verwendet wird . Weil:
using namespace xyz
.using namespace std
Sie sich möglicherweise nicht all der Dinge bewusst, die Sie greifen - und wenn Sie eine weitere hinzufügen#include
oder zu einer neuen C ++ - Version wechseln, können Namenskonflikte auftreten, die Ihnen nicht bekannt waren.Sie können es lokal verwenden
Gehen Sie voran und verwenden Sie es lokal (fast) frei. Dies verhindert natürlich, dass Sie sich wiederholen
std::
- und Wiederholung ist auch schlecht.Eine Redewendung für die lokale Verwendung
In C ++ 03 gab es eine Redewendung - Boilerplate-Code - zum Implementieren einer
swap
Funktion für Ihre Klassen. Es wurde vorgeschlagen, dass Sie tatsächlich ein lokales verwendenusing namespace std
- oder zumindestusing std::swap
:Dies macht die folgende Magie:
std::swap
fürvalue_
, dhvoid std::swap(int, int)
.void swap(Child&, Child&)
implementiert haben, wählt der Compiler diese aus.void std::swap(Child&,Child&)
und versuchen, diese am besten auszutauschen.Mit C ++ 11 gibt es keinen Grund mehr, dieses Muster zu verwenden. Die Implementierung von
std::swap
wurde geändert, um eine mögliche Überlastung zu finden und auszuwählen.quelle
swap
in C ++ 11 nicht mehr so wichtig ist, da diestd::swap
selbst flexibler ist (verwendet die Bewegungssemantik). Aberstd::swap
automatisch Ihren eigenen Swap zu wählen, das ist absolut neu für mich (und ich glaube es nicht wirklich).using std::swap;
als das Schreibenusing namespace std;
. Die spezifischere Sprache hat weniger Nebenwirkungen und macht den Code daher wartbarer.swap
, und verschiedene andere Stellen im Standard wurden geändert, um zu sagen, dass sie so anrufenswap
(NB, wie oben angegeben,using std::swap
ist der richtige Weg, nichtusing namespace std
). Aberstd::swap
selbst wurde nachdrücklich nicht verändert, um andere zu findenswap
und zu nutzen. Wenn esstd::swap
angerufen wird,std::swap
wird es verwendet.using std::swap
lokal einzugeben, um den lokalen Namespace zu verkleinern und gleichzeitig selbstdokumentierenden Code zu erstellen. Sie sind selten jemals an dem gesamten Standard-Namespace interessiert, wählen Sie also einfach die Teile aus, an denen Sie interessiert sind.Wenn Sie die richtigen Header - Dateien importieren Sie plötzlich Namen wie
hex
,left
,plus
odercount
in Ihrem globalen Rahmen. Dies kann überraschend sein, wenn Sie nicht wissen, dassstd::
diese Namen enthalten sind. Wenn Sie auch versuchen, diese Namen lokal zu verwenden, kann dies zu Verwirrung führen.Wenn sich alle Standardmaterialien in einem eigenen Namespace befinden, müssen Sie sich keine Gedanken über Namenskollisionen mit Ihrem Code oder anderen Bibliotheken machen.
quelle
distance
. Trotzdem bevorzuge ich nicht qualifizierte Namen, wo immer dies praktisch möglich ist, da dies die Lesbarkeit für mich erhöht. Außerdem denke ich, dass die Tatsache, dass wir Dinge in der mündlichen Rede normalerweise nicht qualifizieren und bereit sind, Zeit damit zu verbringen, mögliche Unklarheiten zu lösen, bedeutet, dass es wertvoll ist, verstehen zu können, worüber man ohne Qualifikationen spricht, und auf die Quelle angewendet zu werden Code, der bedeutet, dass er so strukturiert ist, dass auch ohne Qualifikation klar ist, worum es geht.<iomanip>
. Trotzdem guter Punkt.Ein weiterer Grund ist die Überraschung.
Wenn ich sehe
cout << blah
, anstatt zustd::cout << blah
denken: Was ist dascout
? Ist es die normalecout
? Ist es etwas Besonderes?quelle
cout
ist ein schlechtes Beispiel, weil jeder es erkennt. Aber stellen Sie sichfuture
in einer Finanz-App vor. Ist es ein Vertrag, etwas zu einem bestimmten Datum zu kaufen oder zu verkaufen? Nein, ist es nicht. Wenn der Code besagt, dassstd::future
Sie nicht so leicht verwirrt sind.Erfahrene Programmierer verwenden alles, was ihre Probleme löst, und vermeiden alles, was neue Probleme verursacht. Aus genau diesem Grund vermeiden sie Verwendungsanweisungen auf Header-Dateiebene.
Erfahrene Programmierer versuchen auch, die vollständige Qualifizierung von Namen in ihren Quelldateien zu vermeiden. Ein kleiner Grund dafür ist, dass es nicht elegant ist, mehr Code zu schreiben, wenn weniger Code ausreicht, es sei denn, es gibt gute Gründe . Ein Hauptgrund dafür ist das Deaktivieren der argumentabhängigen Suche (ADL).
Was sind diese guten Gründe ? Manchmal möchten Programmierer ADL explizit deaktivieren, manchmal möchten sie eindeutig unterscheiden.
Folgendes ist also in Ordnung:
quelle
Ich bin damit einverstanden, dass es nicht global verwendet werden sollte, aber es ist nicht so böse, es lokal zu verwenden, wie in a
namespace
. Hier ist ein Beispiel aus "The C ++ Programming Language" :In diesem Beispiel haben wir mögliche Namenskonflikte und Unklarheiten behoben, die sich aus ihrer Zusammensetzung ergeben.
Dort explizit deklarierte Namen (einschließlich Namen, die durch using-Deklarationen wie deklariert wurden
His_lib::String
) haben Vorrang vor Namen, die durch eine using-Direktive (using namespace Her_lib
) in einem anderen Bereich zugänglich gemacht werden .quelle
Ich halte es auch für eine schlechte Praxis. Warum? Nur eines Tages dachte ich, dass die Funktion eines Namespace darin besteht, Dinge zu teilen, also sollte ich es nicht verderben, alles in eine globale Tasche zu werfen.
Wenn ich jedoch häufig 'cout' und 'cin' verwende, schreibe ich:
using std::cout; using std::cin;
in die CPP-Datei (niemals in die Header-Datei, mit der sie sich verbreitet#include
). Ich denke, dass niemand vernünftig jemals einen Streamcout
oder nennen wirdcin
. ;)quelle
Es ist schön, Code zu sehen und zu wissen, was er tut. Wenn ich sehe,
std::cout
weiß ich, dass das dercout
Stream derstd
Bibliothek ist. Wenn ichcout
dann sehe, weiß ich es nicht. Es könnte dercout
Strom derstd
Bibliothek sein. Oder es könntenint cout = 0;
zehn Zeilen höher in derselben Funktion sein. Oder einestatic
Variable mit dem Namencout
in dieser Datei. Es könnte alles sein.Nehmen Sie jetzt eine Millionen-Zeilen-Codebasis, die nicht besonders groß ist, und suchen Sie nach einem Fehler, was bedeutet, dass Sie wissen, dass diese eine Million Zeilen eine Zeile enthält, die nicht das tut, was sie tun soll.
cout << 1;
könnte einenstatic int
Namen lesencout
, ihn um ein Bit nach links verschieben und das Ergebnis wegwerfen. Auf der Suche nach einem Fehler müsste ich das überprüfen. Kannst du sehen, wie ich es wirklich wirklich vorziehe zu sehenstd::cout
?Es ist eines dieser Dinge, die eine wirklich gute Idee zu sein scheinen, wenn Sie Lehrer sind und nie Code schreiben und pflegen mussten, um ihren Lebensunterhalt zu verdienen. Ich liebe es, Code zu sehen, wo (1) ich weiß, was er tut; und (2) ich bin zuversichtlich, dass die Person, die es schreibt, wusste, was es tut.
quelle
Es geht darum, Komplexität zu managen. Wenn Sie den Namespace verwenden, werden Dinge eingezogen, die Sie nicht möchten, und daher wird das Debuggen möglicherweise schwieriger (ich sage möglicherweise). Die Verwendung von std :: überall ist schwieriger zu lesen (mehr Text und all das).
Pferde für Kurse - verwalten Sie Ihre Komplexität so gut Sie können und fühlen Sie sich in der Lage.
quelle
Erwägen
Beachten Sie, dass dies ein einfaches Beispiel ist. Wenn Sie Dateien mit 20 Includes und anderen Importen haben, müssen Sie eine Menge Abhängigkeiten durchlaufen, um das Problem herauszufinden. Das Schlimmste daran ist, dass Sie abhängig von den widersprüchlichen Definitionen in anderen Modulen nicht verwandte Fehler erhalten können.
Es ist nicht schrecklich, aber Sie sparen sich Kopfschmerzen, wenn Sie es nicht in Header-Dateien oder im globalen Namespace verwenden. Es ist wahrscheinlich in Ordnung, dies in sehr begrenzten Bereichen zu tun, aber ich hatte nie ein Problem damit, die zusätzlichen fünf Zeichen einzugeben, um zu klären, woher meine Funktionen stammen.
quelle
Sie müssen in der Lage sein, Code zu lesen, der von Personen geschrieben wurde, die andere Meinungen zu Stil und Best Practices haben als Sie.
Wenn Sie nur verwenden
cout
, wird niemand verwirrt. Wenn jedoch viele Namespaces herumfliegen und Sie diese Klasse sehen und nicht genau wissen, was sie bewirkt, fungiert der explizite Namespace als eine Art Kommentar. Sie können auf den ersten Blick sehen, "oh, das ist eine Dateisystemoperation" oder "das macht Netzwerkkram".quelle
Die gleichzeitige Verwendung vieler Namespaces ist offensichtlich ein Rezept für eine Katastrophe, verwendet jedoch nur den Namespace
std
und nur den Namespacestd
ist meiner Meinung nach keine so große Sache, da eine Neudefinition nur durch Ihren eigenen Code erfolgen kann ...Betrachten Sie sie einfach als reservierte Namen wie "int" oder "class" und das war's.
Die Leute sollten aufhören, so anal zu sein. Ihr Lehrer hatte die ganze Zeit recht. Verwenden Sie einfach EINEN Namespace. Das ist der springende Punkt bei der Verwendung von Namespaces. Sie sollten nicht mehr als eine gleichzeitig verwenden. Es sei denn, es ist dein eigenes. Eine Neudefinition wird also nicht stattfinden.
quelle
min
,end
undless
im erscheinenstd::
Namespace. Aber jetzt, wostd::
Tausende von Symbolen enthalten sind, ist es für den Leser nützlich zu wissen, woher ein neues Symbol kommt, das er möglicherweise nicht kennt.Ich stimme den anderen hier zu, möchte aber auf die Bedenken hinsichtlich der Lesbarkeit eingehen. Sie können all dies vermeiden, indem Sie einfach typedefs oben in Ihrer Datei-, Funktions- oder Klassendeklaration verwenden.
Normalerweise verwende ich es in meiner Klassendeklaration, da Methoden in einer Klasse in der Regel mit ähnlichen Datentypen (den Mitgliedern) umgehen und ein typedef die Möglichkeit bietet, einen Namen zuzuweisen, der im Kontext der Klasse von Bedeutung ist. Dies unterstützt tatsächlich die Lesbarkeit in den Definitionen der Klassenmethoden.
und in der Umsetzung:
im Gegensatz zu:
oder:
quelle
Ein konkretes Beispiel zur Klärung des Problems. Stellen Sie sich eine Situation, wo Sie zwei Bibliotheken haben,
foo
undbar
, jede mit ihrem eigenen Namensraum:Nehmen wir nun an, Sie verwenden
foo
undbar
zusammen in Ihrem eigenen Programm wie folgt:An diesem Punkt ist alles in Ordnung. Wenn Sie Ihr Programm ausführen, wird "etwas tun" ausgeführt. Aber später aktualisieren Sie
bar
und sagen wir, es hat sich geändert wie folgt:An dieser Stelle wird ein Compilerfehler angezeigt:
Sie müssen also einige Wartungsarbeiten durchführen, um zu verdeutlichen, dass "a" bedeutet
foo::a
. Das ist unerwünscht, aber zum Glück ist es ziemlich einfach (einfachfoo::
vor allen Anrufen hinzufügena
dass der Compiler dies als mehrdeutig markiert).Stellen Sie sich jedoch ein alternatives Szenario vor, in dem sich die Leiste geändert hat, um stattdessen so auszusehen:
An diesem Punkt
a(42)
bindet sich Ihr Aufruf, plötzlich an etwas zu binden,bar::a
anstattfoo::a
etwas zu tun, und es tut etwas völlig anderes. Keine Compilerwarnung oder so. Ihr Programm beginnt nur stillschweigend, etwas völlig anderes als zuvor zu tun.Wenn Sie einen Namespace verwenden, riskieren Sie ein solches Szenario, weshalb es für Benutzer unangenehm ist, Namespaces zu verwenden. Je mehr Dinge sich in einem Namespace befinden, desto größer ist das Risiko von Konflikten, sodass die Verwendung des Namespace für die Benutzer möglicherweise noch unangenehmer ist
std
(aufgrund der Anzahl der Dinge in diesem Namespace) als für andere Namespaces.Letztendlich ist dies ein Kompromiss zwischen Beschreibbarkeit und Zuverlässigkeit / Wartbarkeit. Die Lesbarkeit kann ebenfalls berücksichtigt werden, aber ich konnte Argumente dafür in beide Richtungen sehen. Normalerweise würde ich sagen, dass Zuverlässigkeit und Wartbarkeit wichtiger sind, aber in diesem Fall zahlen Sie ständig die Kosten für die Beschreibbarkeit für eine ziemlich seltene Auswirkung auf Zuverlässigkeit / Wartbarkeit. Der "beste" Kompromiss bestimmt Ihr Projekt und Ihre Prioritäten.
quelle
Ein Namespace ist ein benannter Bereich. Namespaces werden verwendet, um verwandte Deklarationen zu gruppieren und separate Elemente getrennt zu halten. Beispielsweise können zwei separat entwickelte Bibliotheken denselben Namen verwenden, um auf verschiedene Elemente zu verweisen, ein Benutzer kann jedoch weiterhin beide verwenden:
Das Wiederholen eines Namespace-Namens kann sowohl für Leser als auch für Schriftsteller eine Ablenkung sein. Folglich kann angegeben werden, dass Namen aus einem bestimmten Namespace ohne explizite Qualifikation verfügbar sind. Zum Beispiel:
Namespaces bieten ein leistungsstarkes Tool für die Verwaltung verschiedener Bibliotheken und verschiedener Codeversionen. Insbesondere bieten sie dem Programmierer Alternativen dazu, wie explizit auf einen nichtlokalen Namen verwiesen werden soll.
Quelle: Ein Überblick über die C ++ - Programmiersprache von Bjarne Stroustrup
quelle
Ein Beispiel, bei dem
using namespace std
ein Kompilierungsfehler aufgrund der Mehrdeutigkeit der Zählung ausgelöst wird, was auch eine Funktion in der Algorithmusbibliothek ist.quelle
::count
--Problem gelöst. Normalerweise haben Sie mehr Inhalte aus dem Standard-Namespace als aus anderen Ländern. Wenn Sie also die Namespace-Direktive verwenden, sparen Sie sich möglicherweise die Eingabe.Dies verschlechtert die Leistung Ihrer Software oder Ihres Projekts nicht. Die Aufnahme des Namespace am Anfang Ihres Quellcodes ist nicht schlecht. Die Aufnahme der
using namespace std
Anweisung hängt von Ihren Anforderungen und der Art und Weise ab, wie Sie die Software oder das Projekt entwickeln.Das
namespace std
enthält die C ++ - Standardfunktionen und -variablen. Dieser Namespace ist nützlich, wenn Sie häufig die C ++ - Standardfunktionen verwenden.Einige Leute hatten gesagt, dass es eine schlechte Praxis ist, die
using namespace std
in Ihre Quelldateien aufzunehmen, da Sie von diesem Namespace aus alle Funktionen und Variablen aufrufen. Wenn Sie eine neue Funktion mit demselben Namen wie eine andere in der enthaltene Funktion definierennamespace std
möchten, überladen Sie die Funktion und es können Probleme beim Kompilieren oder Ausführen auftreten. Es wird nicht wie erwartet kompiliert oder ausgeführt.quelle
Ich denke nicht, dass es unter allen Umständen unbedingt eine schlechte Praxis ist, aber Sie müssen vorsichtig sein, wenn Sie es verwenden. Wenn Sie eine Bibliothek schreiben, sollten Sie wahrscheinlich die Bereichsauflösungsoperatoren mit dem Namespace verwenden, um zu verhindern, dass Ihre Bibliothek mit anderen Bibliotheken in Kontakt kommt. Für Code auf Anwendungsebene sehe ich nichts Falsches daran.
quelle
"Warum 'Namespace std verwenden;' als schlechte Praxis in C ++ angesehen? "
Ich habe es anders herum ausgedrückt: Warum wird das Eingeben von fünf zusätzlichen Zeichen von manchen als umständlich angesehen?
Denken Sie beispielsweise daran, eine numerische Software zu schreiben. Warum sollte ich überhaupt in Betracht ziehen, meinen globalen Namespace zu verschmutzen, indem ich "std :: vector" auf "vector" reduziere, wenn "vector" eines der wichtigsten Konzepte der Problemdomäne ist?
quelle
cout << hex << setw(4) << i << endl;
ist leichter zu lesen alsstd::cout << std::hex << std::setw(4) << i << std::endl;
std::map<std::string,std::pair<std::string,std::string>>
ist schrecklich im Vergleich zumap<string,pair<string,string>>
.Ich stimme anderen zu - es fragt nach Namenskonflikten, Unklarheiten und dann ist die Tatsache, dass es weniger explizit ist. Während ich die Verwendung von sehen kann
using
, ist es meine persönliche Präferenz, sie einzuschränken. Ich würde auch stark darüber nachdenken, worauf einige andere hingewiesen haben:Wenn Sie einen Funktionsnamen suchen möchten, der möglicherweise ein ziemlich gebräuchlicher Name ist, ihn aber nur im
std
Namespace finden möchten (oder umgekehrt - Sie möchten alle Aufrufe ändern, die sich nicht im Namespacestd
, NamespaceX
usw. befinden), Wie schlagen Sie das vor?Sie könnten ein Programm schreiben, um dies zu tun, aber wäre es nicht besser, Zeit damit zu verbringen, an Ihrem Projekt selbst zu arbeiten, als ein Programm zu schreiben, um Ihr Projekt zu warten?
Persönlich stört mich das
std::
Präfix eigentlich nicht . Ich mag das Aussehen mehr als es nicht zu haben. Ich weiß nicht, ob das daran liegt, dass es explizit ist und zu mir sagt "das ist nicht mein Code ... ich verwende die Standardbibliothek" oder ob es etwas anderes ist, aber ich denke, es sieht besser aus. Dies könnte seltsam sein, da ich erst vor kurzem in C ++ eingestiegen bin (C und andere Sprachen werden viel länger verwendet und immer noch verwendet und C ist meine Lieblingssprache aller Zeiten, direkt über der Assembly).Es gibt noch eine andere Sache, obwohl sie etwas mit dem oben Gesagten zu tun hat und worauf andere hinweisen. Obwohl dies eine schlechte Praxis sein kann, reserviere ich manchmal
std::name
die Standardbibliotheksversion und den Namen für die programmspezifische Implementierung. Ja, in der Tat könnte dies Sie beißen und Sie hart beißen, aber es kommt darauf an, dass ich dieses Projekt von Grund auf neu gestartet habe und ich der einzige Programmierer dafür bin. Beispiel: Ich überladestd::string
und nenne esstring
. Ich habe hilfreiche Ergänzungen. Ich habe es teilweise aufgrund meiner C- und Unix-Tendenz (+ Linux) zu Kleinbuchstaben gemacht.Außerdem können Sie Namespace-Aliase haben. Hier ist ein Beispiel dafür, wo es nützlich ist, auf das möglicherweise nicht Bezug genommen wurde. Ich benutze den C ++ 11 Standard und speziell mit libstdc ++. Nun, es hat keine vollständige
std::regex
Unterstützung. Sicher, es wird kompiliert, aber es löst eine Ausnahme aus, da es sich um einen Fehler des Programmierers handelt. Aber es ist mangelnde Umsetzung.So habe ich es gelöst. Installieren Sie den regulären Ausdruck von Boost und verknüpfen Sie ihn. Anschließend gehe ich folgendermaßen vor: Wenn libstdc ++ ihn vollständig implementiert hat, muss ich nur diesen Block entfernen und der Code bleibt gleich:
Ich werde nicht darüber streiten, ob das eine schlechte Idee ist oder nicht. Ich werde jedoch argumentieren, dass es es für mein Projekt sauber hält und es gleichzeitig spezifisch macht: Richtig, ich muss Boost verwenden, aber ich verwende es so, wie es libstdc ++ irgendwann haben wird. Ja, das Starten eines eigenen Projekts und das Beginnen mit einem Standard (...) am Anfang trägt wesentlich dazu bei, Wartung, Entwicklung und alles, was mit dem Projekt zu tun hat, zu unterstützen!
Nur um etwas zu verdeutlichen: Ich halte es eigentlich nicht für eine gute Idee, einen Namen einer Klasse / was auch immer in der STL absichtlich und genauer anstelle von zu verwenden. Die Zeichenfolge ist für mich die Ausnahme (ignorieren Sie das erste, obige oder zweite Wortspiel, wenn Sie müssen) für mich, da mir die Idee von 'Zeichenfolge' nicht gefallen hat.
So wie es ist, bin ich immer noch sehr voreingenommen gegenüber C und voreingenommen gegenüber C ++. Sparsame Details, vieles, woran ich arbeite, passt mehr zu C (aber es war eine gute Übung und eine gute Möglichkeit, mich dazu zu bringen, a. Eine andere Sprache zu lernen und b. Nicht weniger voreingenommen gegenüber Objekten / Klassen / usw. zu sein, was vielleicht besser gesagt wird als weniger verschlossen, weniger arrogant und mehr akzeptierend.). Aber was nützlich ist , ist das, was einige bereits vorgeschlagen haben: Ich verwende tatsächlich list (es ist ziemlich allgemein, nicht wahr?) Und sortiere (dasselbe), um zwei zu benennen, die einen Namenskonflikt verursachen würden, wenn ich das tun würde
using namespace std;
, und so weiter Zu diesem Zweck bevorzuge ich es, spezifisch zu sein, die Kontrolle zu behalten und zu wissen, dass ich es spezifizieren muss, wenn ich beabsichtige, dass es die Standardverwendung ist. Einfach gesagt: keine Annahme erlaubt.Und was Boosts Regex angeht
std
. Ich mache das für die zukünftige Integration und - ich gebe wieder zu, dass dies Voreingenommenheit ist - ich denke nicht, dass es so hässlich ist wieboost::regex:: ...
. In der Tat ist das eine andere Sache für mich. Es gibt viele Dinge in C ++, die ich in Aussehen und Methoden noch nicht vollständig akzeptiert habe (ein weiteres Beispiel: Variadische Vorlagen versus Var-Argumente [obwohl ich zugebe, dass Variadische Vorlagen sehr, sehr nützlich sind!]). Sogar diejenigen, die ich akzeptiere, waren schwierig und ich habe immer noch Probleme mit ihnen.quelle
std
Namespace ist ein undefiniertes Verhalten und sollte daher niemals durchgeführt werden.Nach meinen Erfahrungen können Sie, wenn Sie mehrere Bibliotheken haben, die beispielsweise verwenden
cout
, aber für einen anderen Zweck die falsche verwendencout
.Wenn ich zum Beispiel
using namespace std;
undusing namespace otherlib;
und nurcout
(was zufällig in beiden ist) anstelle vonstd::cout
(oder'otherlib::cout'
) eingebe, verwenden Sie möglicherweise die falsche und erhalten Fehler. Es ist viel effektiver und effizienter zu bedienenstd::cout
.quelle
Bei nicht qualifizierten importierten Bezeichnern benötigen Sie externe Suchwerkzeuge wie grep , um herauszufinden, wo Bezeichner deklariert sind. Dies erschwert das Nachdenken über die Programmkorrektheit.
quelle
Es hängt davon ab, wo es sich befindet. Wenn es sich um einen allgemeinen Header handelt, verringern Sie den Wert des Namespace, indem Sie ihn mit dem globalen Namespace zusammenführen. Denken Sie daran, dies könnte eine gute Möglichkeit sein, Modulglobale zu erstellen.
quelle
Dies ist eine schlechte Praxis, die oft als globale Verschmutzung durch Namespaces bezeichnet wird. Probleme können auftreten, wenn mehr als ein Namespace denselben Funktionsnamen mit Signatur hat. Dann muss der Compiler nicht eindeutig entscheiden, welchen er aufrufen möchte
std::cout
. Dies alles kann vermieden werden, wenn Sie den Namespace mit Ihrem Funktionsaufruf wie angeben . Hoffe das hilft. :) :)quelle
Um Ihre Frage zu beantworten, sehe ich das praktisch so: Viele Programmierer (nicht alle) rufen den Namespace std auf. Daher sollte man es sich zur Gewohnheit machen, KEINE Dinge zu verwenden, die die gleichen Namen wie im Namespace std beeinflussen oder verwenden. Das ist sehr selbstverständlich, aber nicht so sehr im Vergleich zu der Anzahl möglicher zusammenhängender Wörter und Pseudonyme, die genau genommen gefunden werden können.
Ich meine wirklich ... zu sagen "Verlasse dich nicht darauf, dass dies vorhanden ist" bedeutet nur, dich darauf vorzubereiten, dass es NICHT vorhanden ist. Sie werden ständig Probleme haben, Codefragmente auszuleihen und ständig zu reparieren. Halten Sie einfach Ihre benutzerdefinierten und ausgeliehenen Inhalte in einem begrenzten Umfang, wie sie sein sollten, und gehen Sie SEHR sparsam mit Globals um (ehrlich gesagt sollten Globals fast immer das letzte Mittel sein, um "jetzt kompilieren, später vernünftig"). Wirklich, ich denke, es ist ein schlechter Rat von Ihrem Lehrer, weil die Verwendung von std sowohl für "cout" als auch für "std :: cout" funktioniert, aber NICHT für "std :: cout". Sie werden nicht immer das Glück haben, Ihren gesamten Code zu schreiben.
HINWEIS: Konzentrieren Sie sich nicht zu sehr auf Effizienzprobleme, bis Sie tatsächlich ein wenig über die Funktionsweise von Compilern gelernt haben. Mit ein wenig Erfahrung im Codieren müssen Sie nicht so viel über sie lernen, bevor Sie erkennen, wie viel sie in der Lage sind, guten Code in etwas Einfaches zu verallgemeinern. Genauso einfach, als ob Sie das Ganze in C geschrieben hätten. Guter Code ist nur so komplex, wie er sein muss.
quelle
<algorithm>
z. B. Dinge neu erfinden ), scheint es ein bisschen schwierig zu sein, sich vorzustellen, dass dieselben Personen diese Kennungen zuverlässig vermeiden könnten. Sehen Sie sich Ihren eigenen Code an und sagen Sie mir, dass Sie niemals eine Variable oder Funktion aufgerufen habencount
. Oderdistance
, oderlog
,destroy
,launch
,visit
,beta
,sample
,messages
,clamp
,erase
,copy
,modulus
,left
, etc. Nicht alle die Kennungen noch nicht in erwähnen ,std
dass brechen Sie den Code , wenn C ++ 35 kommt ...