2016-07-14 19 views
5

Betrachten Sie diesen Code:In welcher Compilierungseinheit lebt eine constexpr-Variable?

struct foo 
{ 
    static constexpr int value = 42; 
}; 

void bar(const int* value) { std::cout << *value; } 
int main() { bar(&foo::value); } 

Dieses feine und ohne Warnungen unter dem couple von online compilers kompiliert ich versuchte. Da es keine einzige .cpp Datei gibt, die den Wert constexpr definiert, könnte der Wert des Zeigers unterschiedlich sein, wenn die bar-Methode von verschiedenen Kompilierungseinheiten aufgerufen wird? Oder garantiert der Standard, dass der Wert über alle Übersetzungseinheiten hinweg nur einmal vergeben wird (dh eine implizite)?

+0

Haben Sie gerade das Programm kompiliert oder verlinkt? –

+1

Sobald Sie die Adresse tatsächlich verwenden (http://ideone.com/Bi5oEt), müssen Sie eine Definition angeben. –

+0

Dieser Code verstößt gegen die Definition für eine Definition. Da dies jedoch ein nicht definiertes Verhalten ist, müssen Compiler keine Warnungen ausgeben. – cpplearner

Antwort

9

Es funktioniert nicht für mich --- Ich bekomme einen Linker-Fehler. http://coliru.stacked-crooked.com/a/59e2cf56122733d0

Wenn Sie das tun nicht odr-verwenden die statische constexpr-Mitglied können Sie sich vorstellen, dass es inlined ist überall dort, wo erforderlich und lebt nicht in jeder Übersetzungseinheit. Wenn Sie tun odr-verwenden Sie es, wie Sie in Ihrem Programm getan haben, müssen Sie definieren.

+0

Und wie definieren Sie es? Ich dachte, der Wert müsste bei der Deklaration als Constexpr verwendet werden. Ordnen Sie es sowohl bei der Deklaration als auch bei der Definition zu? – Trillian

+0

@Trillian Wenn Sie es in der Deklaration initialisieren, initialisieren Sie es nicht in der Definition. – Brian

+0

Ja, aber consxpr erfordert keine Initialisierung bei der Deklaration und odr Initialisierung bei der Definition? – Trillian

1

Im Allgemeinen die Adresse eines Objekts zu nehmen, stellt eine odr-Verwendung dar, die es erforderlich machen würde, das Objekt irgendwo zu definieren (was Linkerfehler verursacht, wenn dies nicht der Fall ist). Die Adressübernahme kann jedoch als keine odr-Verwendung betrachtet werden, wenn der resultierende Ausdruck ein verworfener Wert ist. Es könnte sein, dass Ihre Verwendung davon von einigen Compilern so behandelt wird, dass sie in die Ausnahme fallen, da sie als Parameter an eine Funktion übergeben werden, die sie sofort verwirft.

4

Die anderen Antworten sind korrekt, aber die Situation wird sich in C++ 17 mit der Annahme inline variables (p0386) ändern. constexpr wird dann inline anzeigen.

+1

Um klar zu sein, nur "constexpr" auf einem statischen Klassenmitglied bedeutet inline :-) –