2010-01-18 14 views
10

Wie funktioniert der folgende Code in C++? Ist es logisch?Literal-Initialisierung für Const-Referenzen

Warum erlaubt C++ die Literalinitialisierung für Const-Referenzen, wenn diese für nicht-konstante Referenzen nicht zulässig sind? Z.B .:

const int days_of_week = 7; 
int &dof = days_of_week; //error: non const reference to a const object 

Dies kann durch die Tatsache erklärt werden, dass eine nicht konstante Referenz verwendet werden kann, um den Wert der Variablen zu ändern, es sich bezieht. Daher erlaubt C++ keinen nichtkonstanten Verweis auf eine const-Variable.

Könnte dies eine mögliche Erklärung sein? C++ nicht erlaubt:

int &ref = 7; 

Denn das ist nicht logisch, aber:

const int &ref = 7; 

fast gleichwertig ist:

const int val = 7; 

So wörtliche Initialisierung für konstante Variablen erlaubt.

P.S .: Ich studiere gerade Lippman C++ Primer.

Antwort

7

So können Sie Code wie folgt schreiben:

void f(const string & s) { 
} 

f("foobar"); 

Obwohl streng genommen, was hier eigentlich geschieht, ist nicht die wörtliche auf eine konstante Referenz gebunden zu sein - stattdessen ein temprary String-Objekt erstellt:

string("foobar"); 

und diese namenlose Zeichenfolge ist an die Referenz gebunden.

Beachten Sie, dass es tatsächlich ziemlich ungewöhnlich ist, Referenzvariablen nicht-Parameter zu erstellen, während Sie tun - der Hauptzweck von Referenzen ist als Funktionsparameter und Rückgabewerte dienen.

6

Konstante Referenzen können mit Literalen und Provisorien initialisiert werden, da Sie trivialer sie explizite Variablen umwandeln können:

int const& ans = 42; 
// tranformed: 
int __internal_unique_name = 42; 
int const& ans = __internal_unique_name; 

Oder, wenn die Lebensdauer nicht verlängert, wie Funktionsparameter:

f("foobar"); 
// transformed: 
{ 
    string __internal_unique_name = "foobar"; 
    f(__internal_unique_name); 
} 

(Beachten Sie den expliziten Block in diesem Fall.)

Während es im nichtkonstanten Fall möglich ist, etwas Ähnliches zu tun, ist das nicht der Fall erlaubt in currenct C++. C++ 0x (der nächste Standard) wird jedoch r-Wert-Referenzen haben.


Wenn es nicht klar war, ref + 6 aus dem Code erstellt ein temporäres Objekt, das Sie sich vorstellen kann, wie:

int const& ref = int(9); 
int const& another_ref = int(ref + 6); 

// transformed: 
int __A = 9; 
int const& ref = __A; 
int __B = ref + 6; 
int const& another_ref = __B; 

Dies können Ihnen helfen, zu verstehen/visualisieren, was geschieht, aber Sie sollten schreibe keinen echten Code wie diesen.Außerdem habe ich doppelte Unterstrichnamen verwendet, um diese Namen als Implementierungsdetails zu veranschaulichen (die vom Compiler verwendet werden) und sollten nicht von Ihnen verwendet werden. Jeder Name, der benachbarte Unterstriche enthält, ist für die C++ - Implementierung reserviert.

+0

+1. Aber ich denke, Ihr zweites Beispiel würde in { string __internal_unique_name ("foobar") umgewandelt werden; f (__ interner_eindeutiger_Name); } – mmmmmmmm

+0

@rstevens: Es spielt keine Rolle: Die Konvertierung darf nicht explizit sein, in diesem Fall sind sie gleich. –

2

Ihr Code läuft auf die C++ - Standardregel hinaus, in der die Lebensdauer eines temporären Werts an die Lebensdauer des const-Verweises gebunden ist, dem er zugewiesen ist. Weitere Details finden Sie im Artikel GotW #88: A Candidate For the “Most Important const”GoTW. Die von Alexandrescu und Marginean im Artikel von Dr. Dobbs "Generic: Change the Way You Write Exception-Safe Code — Forever" beschriebene Implementierung ScopeGuard hängt beispielsweise von diesem Verhalten ab.

Verwandte Themen