2015-10-13 13 views
28
using ::std::...; 

VSUnterschied in using namespace (std :: vs :: std: :)

using std::...; 

Gibt es einen Unterschied (n)? Wenn ja, welche)?

sah ich dies:

using ::std::nullptr_t; 

, die mich fragen, gemacht.

+12

Sie müssen ':: std :: nullptr_t' nur schreiben, wenn jemand anderes ein' std :: nullptr_t' zu einem verschachtelten Namespace in Ihrem Projekt hinzufügt. Oder du könntest deinen Manager dazu bringen, mit diesem Typen ein ernsthaftes Gespräch zu führen. –

+3

BTW ein 'Namespace C14_compatibility {Namespace std {Vorlage mit Verwendung von Decay_t = Typname Zerfall :: Typ; }} 'und' mit Namespace C14_compatibility; 'scheint eine mögliche Verwendung. – Jarod42

+0

Oder in der Tat, wenn Ihr Compiler nicht den C++ - Standard unterstützt, den Sie verwenden möchten, oder es tut, aber Sie benötigen an einigen Stellen Ihre eigene Implementierung. – OrangeDog

Antwort

31

In Ihrem Fall gibt es höchstwahrscheinlich keinen Unterschied. Jedoch in der Regel wird die Differenz wie folgt:

using A::foo; löst A vom aktuellen Umfang, während using ::A::foo sucht nach A aus dem Stammnamespace.Zum Beispiel:

namespace A 
{ 
    namespace B 
    { 
     class C; 
    } 
} 
namespace B 
{ 
    class C; 
} 
namespace A 
{ 
    using B::C; // resolves to A::B::C 
    using ::B::C; // resolves to B::C 
    // (note that one of those using declarations has to be 
    // commented for making this valid code!) 
} 
+2

Dieser Unterschied ist sehr wichtig beim Schreiben von Makros. Ein Makro wird überall dort erweitert, wo der Entwickler es verwendet. Das Makro kann nicht annehmen, dass 'std' genau dorthin geht, wo es sein soll. Daher verwenden Makros oft' :: std', um sicherzustellen, dass das Makro keine unerwarteten Überraschungen aufweist. –

8

Von: http://en.cppreference.com/w/cpp/language/using_declaration

Mit-Deklaration ein Mitglied eines anderen Namespace in aktuellen Namensraum einführt oder Umfang

Daher blockieren, wenn Ihr bereits aktuellen Bereich eine Klasse mit dem gleichen Namen hat, Es wird eine Zweideutigkeit zwischen der von Ihnen eingegebenen und der in Ihrem aktuellen Namespace/Block bestehen.

Eine using-Deklaration ist nur eine Teilmenge einer using-Anweisung. Die Verwendung von Richtlinien wie folgt definiert sind (http://en.cppreference.com/w/cpp/language/namespace):

Aus der Sicht von unqualifizierter Namen-Suche von einem beliebigen Namen nach einem mit-Richtlinie und bis zum Ende des Bereichs, in dem es erscheint, alle Namen from namespace-name ist sichtbar, als ob es in dem nächsten umschließenden Namespace deklariert wäre, der sowohl die using-Direktive als auch den Namespace-name enthält.

So können Sie diese zwei Beispiele betrachten, die die Probleme anzeigen, die auftreten können.

Es verhindert Mehrdeutigkeit zwischen Namespaces, die den gleichen Namen (Beispiel 1) sowie Ambiguität zwischen Klassennamen in verschiedenen Namespaces (Beispiel 2).

namespace A 
{ 
    namespace B 
    { 
     struct my_struct {}; 
    } 
} 

namespace B 
{ 
    struct my_struct {}; 
} 

using namespace A; // removing this line makes B:: resolve to the global B:: 

int main() 
{ 
    ::B::my_struct; // from global, will not pick A::B:: 

    B::my_struct; // error: 'B' is ambiguous, there is A::B:: and B:: 
} 

Betrachten Sie dieses Beispiel, das zeigt, warum die Menschen die Verwendung von using namespace std;

using namespace std; 

template <typename T> 
class vector 
{ }; 

int main() 
{ 
    vector<int> v; // which one did you want? ambiguous 
    ::vector<int> v_global;  // global one 
    ::std::vector<int> v_std; // std::vector<T> 
} 
+0

Wie würde die using-Direktive in diesem Fall verwendet werden, um sie mit der Frage in Einklang zu bringen? – dspfnder

+0

Im Allgemeinen ist das wahr, aber diese Frage bezieht sich auf 'using' Typen aus einem Namespace, nicht den gesamten Namespace! – anderas

+0

@anderas Der Unterschied zwischen einer using-Deklaration und einer using-Anweisung ist nicht so groß. Sie können es einfach sehen, wenn Sie einen einzelnen Typ in den aktuellen Bereich einbringen und der andere führt alle Typen in den aktuellen Bereich ein. –

5

Es hängt davon ab, zu meiden, wo Sie die using Erklärung verwenden. In einem globalen Namespace-Bereich gibt es keinen Unterschied. Wenn Sie jedoch haben Code wie

#include <iostream> 
#include <vector> 

namespace my_namespace { 
    namespace std { 
     class vector { 
     }; 
    } 

    using std::vector; 
} 

int main() 
{ 
    my_namespace::vector<int> v; 
} 

es wird nicht kompiliert, wenn Sie den Compiler informiert den globalen Namespace suchen -> std-Namespace -> Vektor in Ihrer Erklärung using ::std::vector Angabe.

+2

Auf der anderen Seite verdienen Leute, die der Quelle einen zusätzlichen Namensraum 'std' hinzufügen, um gefeuert zu werden. Das ist viel einfacher, als wenn alle anderen ':: std ::' überall schreiben. –

+0

@BoPersson Natürlich :) Ich illustrierte nur den Unterschied. Es ist wahrscheinlich nur die Vorliebe des Entwicklers, ':: std :: ...' zu schreiben. – Rostislav

+0

@BoPersson: Ich habe einen Kommentar in der OP-Frage hinzugefügt, der ein praktikabler Grund dafür scheint, 'namespace std' im Benutzer-Namespace zu haben. – Jarod42

10

Wenn Sie in einem anderen Namensraum, der seinen eigenen verschachtelten std Namensraum hat, dann ::std und std unterschiedlich sind. Ein einfaches Beispiel:

#include <iostream> 

namespace A { 
    namespace std { 
     void foo() { ::std::cout << "foo" << ::std::endl;} 
    } 
    //using std::cout; // compile error 
    using ::std::cout; //ok 

    using std::foo; // ok 
    //using ::std::foo; // compile error 
} 

Obwohl definitiv keine gute Praxis, jemals einen verschachtelten std Namespace.

+0

Also ':: std ::' sagt, um den globaleren Namespace von Std zu nehmen? Oh, Andreas macht es in seiner Antwort klar, danke, +1. – gsamaras

+3

@gsamaras, nicht nur die globalere, sondern die (einzige), die absolut global ist, nirgendwo verschachtelt. – Petr

Verwandte Themen