2017-03-01 3 views
5

Dies ist im Grunde eine Fortsetzung von my prior question über DR 712. Lassen Sie mich zuerst erklären, warum ich darauf beharre, etwas zu betrachten, das als alt angesehen werden könnte, wie die C++ 11 Standard, aber mein Problem ist, dass der Abschnitt [basic.def.odr] in C++ 11 schon schwer zu verstehen ist, und ich möchte das vollständig abdecken, bevor ich mich in den gleichen Abschnitt im aktuellen Entwurf vertiefe, was meiner Meinung nach ist noch komplizierter. Die Antwort auf meine vorherige Frage von Austing Hasting s war großartig, aber ich habe noch einen kleinen Punkt, der in [basic.def.odr]/2 in C++ 11 nicht klar ist Betrachten Sie dieses kleine und sehr einfaches Beispiel:Fortsetzung von "Ich kann einfach nicht verstehen, DR 712"

const int i = 1; 
int main() 
{ 
    int j = i; 
} 

Von [basic.def.odr]/2 in C++ 11 i ist nichtodr-used in int j = i; als i ist ein Objekt, das in der Anforderung genügt für das Erscheinen Ein konstanter Ausdruck und die lvalue-to-rvalue-Konvertierung wird sofort auf i angewendet. Das macht für mich keinen Sinn, da i eindeutig in der Deklaration int j = i; verwendet wird, wie in dem leicht modifizierten Code here zu sehen ist, wo ich die Variable i gezwungen habe, nicht aus dem kompilierten Code optimiert zu werden.

Natürlich muss etwas falsch in meiner Argumentation oben sein, denn ich glaube nicht, dass C++ 11 in so einem einfachen Beispiel falsch liegen könnte. Nochmal, was vermisse ich jetzt ???

+4

Alles, was in Ihrem Beispielcode benötigt wird, ist *** der Wert *** von "i". Das bedeutet, dass es weg optimiert werden kann und keinen zugewiesenen Speicher benötigt. –

Antwort

9

Ich versuche, mein Verständnis von Standard "Used" und "One Definition Regel verwendet" zu etwas intuitiver hier zu übersetzen. Begriffe, die nicht "verwendet" und "ODR-verwendet" sind, sind nicht als standarddefinierte Begriffe unten definiert.


Etwas ODR-verwendet bedeutet im Grunde "wir brauchen es, um eine Identität zu haben". Dies bedeutet normalerweise, dass jemand eine Referenz oder einen Zeiger darauf nimmt.

Wenn Sie nur den Wert Wert von etwas benötigen, macht dies nicht immer ODR-verwendet. Der Wert einer Kompilierzeitkonstante erfordert keine Identität.

In C++ bedeutet Identität im Grunde "es muss tatsächlich Speicher irgendwo haben".

Der Standard sagt nicht, „es ODR verwendet, wenn wir sie brauchen eine Identität zu haben“, weil dann verschiedene Compiler unterschiedliche Regeln haben, um zu bestimmen, ob sie die Identität benötigen . Wenn zum Beispiel eine Operation inline ist und die Referenz entfernt ist, bedeutet das, dass sie keine Identität mehr benötigt?

Also der Standard beschreibt, was ODR-verwendet bedeutet, und unterscheidet es von dem Wert verwendet wird.

int j = i; 

Dies erfordert nicht die Identität i. Es braucht nur seinen Wert. const int i = 1; hat einen Wert, der sich nicht (unter definiertem Verhalten) ändern kann.

int const* pj = &i; 

diese tut eine Identität benötigen. Zwei verschiedene Zeiger auf i müssen den Standort von i unter der Norm vereinbaren.

void foo(const int& x) { 
    int j = x; 
} 
foo(i); 

Dies erfordert auch eine Identität für i. Wir nehmen Bezug auf i. Obwohl das einzige, was wir tun, nur die Bezugnahme auf ihren Wert ist, bedeutet die (kurze, theoretische) Existenz dieser Referenz, dass sie eine Identität hat.

const int a = 3; const int b = 4; 
int i = (a<2)?a:b; 

der Fehler war es, dass dies erforderlich a und b Identität zu haben (sie, wo ODR verwendet), weil das die Wechselwirkung von ? mit den verwendeten-Regeln. Der Fehler lautete: "Wir sollten das reparieren".

Link to DR 712

Und nach dieser Auflösung ist nur der Wert von a und b durch diesen Ausdruck erforderlich ist, nicht ihre Identität, so dass sie nicht brauchen, Lagerung zu haben.

Es ist uns wichtig, wenn etwas Speicher hat, weil Dinge, die Speicher benötigen, einen eindeutigen Definitionspunkt haben müssen. Sie können grundsätzlich nicht rein in einer Header-Datei existieren.

Beachten Sie, dass wir uns mit Inline-Variablen in C++ 17 vielleicht weniger Sorgen machen; Nach der Als-ob-Regel kann der erstellte Inline-Speicherort gelöscht werden, wenn niemand wirklich auf die Identität achtet. Da Funktionen, die const& übernehmen, "versehentlich" Identitätsanforderungen für Dinge erzwingen können, die Wert-Tokens sein sollen, ist dies eine nette Entspannung der Regeln.

+0

Danke für die sehr umfassende Antwort (+1) –

Verwandte Themen