Globale Konstanten in C ++ 11

Was sind die besten Möglichkeiten, globale Konstanten in C ++ zu deklarieren und zu definieren? Ich interessiere mich hauptsächlich für den C ++ 11-Standard, da er in dieser Hinsicht viele Fehler behebt.

[EDIT (Klarstellung)]: In dieser Frage bezeichnet "globale Konstante" eine konstante Variable oder Funktion, die zur Kompilierungszeit in bekannt istirgendein Umfang. Die globale Konstante muss von mehr als einer Übersetzungseinheit aus zugänglich sein. Es ist nicht unbedingt eine Konstante im constexpr-Stil - kann so etwas seinconst std::map<int, std::string> m = { { 1, "U" }, { 5, "V" } }; oderconst std::map<int, std::string> * mAddr() { return & m; }. Ich rühre in dieser Frage nicht den bevorzugten Gültigkeitsbereich oder Namen für die Konstante an. Lassen Sie uns diese Fragen für eine andere Frage belassen. [END_EDIT]

Ich möchte Antworten für all die verschiedenen Fälle wissen, also lassen Sie uns das annehmenT ist eine der folgenden:

typedef    int                     T;  // 1
typedef    long double             T;  // 2
typedef    std::array<char, 1>     T;  // 3
typedef    std::array<long, 1000>  T;  // 4
typedef    std::string             T;  // 5
typedef    QString                 T;  // 6
class      T {
   // unspecified amount of code
};                                     // 7
// Something special
// not mentioned above?                // 8

Ich glaube, dass es kein großes gibtsemantisch (Ich diskutiere hier nicht über gute Benennung oder Gültigkeitsbereich) Unterschied zwischen den 3 möglichen Gültigkeitsbereichen:

// header.hpp
extern const T tv;
T tf();                  // Global
namespace Nm {
    extern const T tv;
    T tf();              // Namespace
}
struct Cl {
    static const T tv;
    static T tf();       // Class
};

Wenn jedoch die Wahl eines besseren Weges aus den unten stehenden Alternativen vom Unterschied zwischen den oben genannten Deklarationsbereichen abhängt, weisen Sie darauf hin.

Betrachten Sie auch den Fall, wenn ein Funktionsaufruf in einer konstanten Definition verwendet wird, z.<some value>==f();. Wie würde der Aufruf einer Funktion in ständiger Initialisierung die Wahl zwischen Alternativen beeinflussen?

Lass uns in Erwägung ziehenT mitconstexpr Konstruktor zuerst. Offensichtliche Alternativen sind:

// header.hpp
namespace Ns {
constexpr T A = <some value>;
constexpr T B() { return <some value>; }
inline const T & C() { static constexpr T t = <some value>; return t; }
const T & D();
}

// source.cpp
const T & Ns::D() { static constexpr T t = <some value>; return t; }

Ich glaube dasA undB sind am besten für kleine geeignetT (so dass das Vorhandensein mehrerer Instanzen oder das Kopieren zur Laufzeit kein Problem darstellt), z.1-3, manchmal7. C undD sind besser wennT ist groß, z.B.4, manchmal7.

T ohneconstexpr Konstrukteur. Alternativen:

// header.hpp
namespace Ns {
extern const T a;
inline T b() { return <some value>; }
inline const T & c() { static const T t = <some value>; return t; }
const T & d();
}

// source.cpp
extern const T Ns::a = <some value>;
const T & Ns::d() { static const T t = <some value>; return t; }

Ich würde normalerweise nicht verwendena wegen statischen Initialisierungsreihenfolge Fiasko. Soweit ich weiss,b, c undd sind absolut sicher, sogar threadsicher seit C ++ 11.b scheint keine gute Wahl zu sein, es sei dennT hat einen sehr billigen Konstruktor, was für Nicht-Constexpr-Konstruktoren ungewöhnlich ist. Ich kann einen Vorteil nennenc Überd - kein Funktionsaufruf (Laufzeitleistung); Ein Vorteil vond Überc - Weniger Neukompilierung, wenn der Wert der Konstante geändert wird (diese Vorteile gelten auch fürC undD). Ich bin mir sicher, dass ich hier viele Argumente verpasst habe. Geben Sie bitte andere Überlegungen in den Antworten an.

Wenn Sie den obigen Code ändern / testen möchten, können Sie meine Testdateien verwenden (nur header.hpp, source.cpp mit kompilierbaren Versionen der obigen Codefragmente und main.cpp, die Konstanten aus header.hpp ausgeben):https://docs.google.com/uc?export=download&id=0B0F-aqLyFk_PVUtSRnZWWnd4Tjg

Antworten auf die Frage(3)

Ihre Antwort auf die Frage