2010-02-23 3 views
9

Kann mir jemand erklären, warum es einen Unterschied zwischen diesen beiden Aussagen gibt?Referenzinitialisierung in C++

class A{}; 

const A& a = A();   // correct 

A& b = A();    // wrong 

Es sagt ungültige Initialisierung einer nicht konstanter Referenz vom Typ A& von einem temporären vom Typ A

Warum const Sache hier?

Antwort

14

Nicht konstante Referenzen müssen mit l-Werten initialisiert werden. Wenn Sie sie mit Provisorien initialisieren könnten, was würde dann Folgendes tun?

int& foo = 5; 
foo = 6; // ?! 

const Referenzen haben die besondere Eigenschaft, dass sie das Leben des Schiedsrichters verlängern, und da sie const sind, gibt es keine Möglichkeit, dass Sie versuchen, etwas zu ändern, die nicht im Speicher nicht sitzen. Zum Beispiel:

const int& foo = 5; 
foo = 6; // not allowed, because foo is const. 

Denken Sie daran, dass Referenzen tatsächlich auf etwas verweisen müssen, nicht nur temporäre Variablen. Zum Beispiel ist das Folgende gültig:

int foo = 5; 
int& bar = foo; 
bar = 6; 
assert(foo == 6); 
+1

Warte, also kann ich 'const classA & ref = ReturnsClassAByValue();'? Ich dachte, die Temperatur würde in der nächsten Zeile sterben. – Lucas

+2

Ja, Sie könnten das verwenden. Die temporäre wird so lange dauern, wie die Referenzvariable: http://herbsutter.spaces.live.com/blog/cns!2D4327CC297151BB!378.entry –

+1

Awesome, danke. Auf SO lernst du jeden Tag etwas Neues ... – Lucas

1

Für einen temporären/rvalue können Sie nur eine const-Referenz haben.

Sie können einen nichtkonstanten Verweis auf einen nicht temporären/lvalue haben.

A a; 
A& b = a; 

Ich glaube, der Grund dafür ist die Tatsache zu verstärken, dass ein R-Wert vorübergehend ist, da es wenig Wert ist in der Lage zu sein, etwas zu ändern, die für einen Moment verschwinden wird.

+1

Zugegeben; Ich denke, das OP sucht nach dem Grund dafür. – fbrereto

1

In C++ - Sprache ist es illegal, einen nichtkonstanten Verweis auf einen rvalue anzuhängen, während es vollkommen in Ordnung ist, einen const-Verweis an einen rvalue anzuhängen. Zum Beispiel ist diese Recht

const int& r = 5; 

während dies nicht

ist
int &r = 5; // ERROR 

Ein temporäres Objekt vom Typ A durch den Ausdruck zurück A() ein R-Wert ist, so dass die obige Regel auch in Ihrem Fall zutrifft.

+0

Ein Rvalue ist ein unbenannter temporärer Wert, wie der Rückgabewert einer Funktion. – thebretness

+0

@thebretness: Nicht unbedingt. Eine Enum-Konstante ist beispielsweise ein R-Wert, wird jedoch * mit * benannt. – AnT

3

Die Terminologie dazu ist ein wenig verwirrend; Vielleicht möchten Sie sie ein wenig weiter erforschen. Hier ist die kurze Antwort:

Sie zuweisen ein temporäres Objekt (das Ergebnis des Aufrufs der Konstruktor der Klasse) auf eine Variable. Ein temporäres Objekt ist ein R-Wert. Sie können einer nicht konstanten Referenz keinen R-Wert zuweisen.

Sie dürfen einer const-Referenz einen R-Wert zuweisen, obwohl das Grundprinzip dafür ziemlich unklar ist.

0

Da der Standard sagt so:

§8.5.3.5 ... Ansonsten wird die Bezugnahme auf einen nichtflüchtigen const Typ L-Wert Referenz sein ...

jedoch, wenn Sie es sehr viel wollen, können Sie es bekommen:

#include <iostream> 
int main() 
{ 
    const int & cr=5; 
    int & r=const_cast<int &>(cr); 
    r=6; 
    std::cout<<r; 
} 
// outputs 6 with c++/clang++, Debian 8, amd64 

aber bewusst sein, dass die vermeintliche konstant cr nicht mehr ist const, auch, und Sie nicht definiertes Verhalten entstehen. (§1.9 (4))

Wie durch den obigen Code vorgeschlagen, gibt es keinen technischen Grund für den Unterschied. Vielmehr hatten die Designer Alpträume darüber, was Benutzer mit nichtkonformen Referenzen zu Provisorien machen würden.