2010-11-15 9 views
14

In C++ macht die Verknüpfung einer Funktion oder einer Variablen in einem anonymen Namespace die Verknüpfung intern, d. e. das gleiche wie deklariert es static auf einer Dateiebene, aber idiomatische C++.Verknüpfung von Symbolen in anonymen Namespace innerhalb eines regulären Namespaces

Was ist mit einem anonymen Namespace in einem normalen Namespace? Garantiert es noch interne Verbindungen?

// foo.cpp 

void func1() { 
    // external linkage 
} 

static void func2() { 
    // internal linkage 
} 

namespace { 
    void func3() { 
     // internal linkage 
    } 
} 

namespace ns1 { 
    void func4() { 
     // external linkage 
    } 

    namespace { 
     void func3() { 
      // still internal linkage? 
     } 
    } 
} 
+1

Falsche Annahme. Variablen innerhalb eines Anonymen-Namespace haben eine externe Verknüpfung, sofern sie nicht als "statisch" deklariert sind. – MSalters

+1

@MSalters: Ich denke, mit C++ 11 hat sich das geändert. '§ 3.5/4: Ein unbenannter Namespace oder ein Namespace, der direkt oder indirekt in einem unbenannten Namespace deklariert ist, hat eine interne Verknüpfung. Alle anderen Namespaces haben eine externe Verknüpfung. – legends2k

+1

@ legends2k: Das ist Teil einer anderen Änderung, die diese Namen als Template-Argumente gültig gemacht hat (In C++ 03 benötigten Template-Argumente externe Verknüpfungen, die von in einem anonymen Namespace definierten Konstanten erfüllt wurden) – MSalters

Antwort

11

C++ 11 (Entwurf N3337) §3.5/4: (Hervorhebung von mir)

Ein ungenannter Namespace oder ein Namensraum direkt oder indirekt innerhalb eines ungenannten Namespace hat interne Bindung erklärt. Alle anderen Namespaces haben eine externe Verknüpfung. Ein Name mit einem Namespace-Bereich, der oben nicht intern angegeben wurde, hat die gleiche Verknüpfung wie der einschließende Namespace, wenn es der Name

- eine Variable ist; oder

- eine Funktion; oder

- eine benannte Klasse (Klausel 9) oder eine unbenannte Klasse, die in einer typedef-Deklaration definiert ist, in der die Klasse den typedef-Namen für Verknüpfungszwecke hat (7.1.3); oder

- eine benannte Aufzählung (7.2) oder eine unbenannte Enumeration, die in einer typedef-Deklaration definiert ist, in der die Enumeration den typedef-Namen für Verknüpfungszwecke hat (7.1.3); oder

- ein Enumerator, der zu einer Enumeration mit Verknüpfung gehört; oder

- eine Vorlage.

Dieses guarentees, dass jede unbenannte Namespace interne Bindung hat.

Was ist mit einem anonymen Namespace in einem normalen Namespace? Garantiert es noch interne Verbindungen?

Obwohl innerhalb einer benannten (normal) Namespace, es ist eine unbenannte (anonym) Namespace und somit als interne Bindung hat garantiert gemäß dem Standard 11 C++.


eine Funktion oder eine Variable in einem anonymen Namespace setzen macht seine Verknüpfung intern, i. e. genauso wie es auf einer Dateiebene statisch deklariert wird, aber idiomatisch C++.

In C++ 11 die Verwendung von static in diesem Zusammenhang war undeprecated; obwohl unnamed namespace is a superior alternative to static, there're instances where it fails, die durch static behoben wird; inline namespace was introduced in C++11 um dies zu adressieren.

15

Es ist nicht unbedingt der Fall, dass Entitäten in einem anonymen Namespace interne Verknüpfung haben; sie können tatsächlich eine externe Verbindung haben.

Da der unbenannte Namespace einen Namen hat, der für die Übersetzungseinheit, in der er kompiliert wurde, eindeutig ist, können Sie unabhängig von der Verknüpfung nicht auf die darin deklarierten Entitäten von außerhalb dieser Übersetzungseinheit verweisen.

Die C++ Standard sagt (C 03 ++ 7.3.1.1/note 82):

Obwohl Entitäten in einem ungenannten Namespace externe Bindung haben könnten, werden sie durch einen eindeutigen Namen, um ihre Übersetzungseinheit effektiv qualifiziert und kann daher nie von einer anderen Übersetzungseinheit gesehen werden.

+2

Eine schnelle Folge: Weißt du, ob eine interne Verknüpfung einem Compiler hilft, bessere Code-Transformationsentscheidungen für seine Optimierungen zu treffen, oder ist das kein Problem? –

+0

@Alex B: Das ist eine gute Frage. Wenn ein Compiler oder Linker Optimierungen für Entitäten mit interner Verknüpfung durchführen kann, könnte ich davon ausgehen, dass dieselben Optimierungen für Entitäten in einem unbenannten Namespace durchgeführt werden können. Das kann ich aber nicht sicher sagen. Andere hier würden es viel besser wissen als ich. –

5

3,5 $/3 - „Ein Name-Namensraum mit Umfang (3.3.6) hat interne Bindung, wenn es der Name

ist

- eine Variable, Funktion oder Funktionsschablone, die ist ausdrücklich erklärt statisch, oder

- eine Variable, die explizit const deklariert wird und weder ausdrücklich erklärt extern noch vorher auf 01 erklärt habenexterne Verbindung; oder

- ein Datenelement einer anonymen Union.

Also, ich bezweifle, wenn einer der Namen "func3" und "func4" in Ihrem Programm interne Verknüpfung überhaupt haben. Sie haben eine externe Verbindung. Es ist jedoch nur so, dass sie nicht in Übereinstimmung mit dem Zitat von James von anderen Übersetzungseinheiten stammen können.