2010-09-27 7 views
15

Ich hörte, dass die temporären Objekte nur zu konstanten Referenzen zugewiesen werden können.Konstante Referenzen mit typedef und Vorlagen in C++

Aber dieser Code gibt Fehler

#include <iostream.h>  
template<class t> 
t const& check(){ 
    return t(); //return a temporary object 
}  
int main(int argc, char** argv){ 

const int &resCheck = check<int>(); /* fine */ 
typedef int& ref; 
const ref error = check<int>();/*error */ 
return 0; 
} 

Der Fehler, der erhalten ist, ist invalid initialization of reference of type 'int&' from expression of type 'const int'

Antwort

21

Dieses:

typedef int& ref; 
const ref error; 

nicht tut, was Sie denken, es tut. Betrachten Sie stattdessen:

typedef int* pointer; 
typedef const pointer const_pointer; 

Die Art der const_pointer ist int* const, nichtconst int *. Das heißt, wenn Sie sagen const T Sie sagen "machen Sie einen Typ, wo T unveränderlich ist"; Im vorherigen Beispiel wird also der Zeiger (nicht der Zeiger) unveränderlich gemacht.

Es können keine Referenzen erstellt werden const oder volatile. Dies ist:

ist bedeutungslos, so hat das Hinzufügen von CV-Qualifier zu Referenzen keine Wirkung.

Daher hat error den Typ int&. Sie können ihm keine const int& zuweisen.


Es gibt andere Probleme in Ihrem Code. Zum Beispiel ist dies sicherlich falsch:

template<class t> 
t const& check() 
{ 
    return t(); //return a temporary object 
} 

Was bist du hier einen Verweis auf ein temporäres Objekt zurückkehrt , die ihre Lebensdauer endet, wenn die Funktion zurückgibt. Das heißt, Sie erhalten ein undefiniertes Verhalten, wenn Sie es verwenden, da sich kein Objekt im Referant befindet. Dies ist nicht besser als:

template<class t> 
t const& check() 
{ 
    T x = T(); 
    return x; // return a local...bang you're dead 
}  

Ein besserer Test wäre:

template<class T> 
T check() 
{ 
    return T(); 
} 

Der Rückgabewert der Funktion vorübergehend ist, so dass Sie immer noch können testen, dass man in der Tat binden Provisorien zu konstanten Referenzen .

+0

Gute Antwort. +1 :) –

+0

Vielen Dank. :) – GManNickG

7

Ihr Code gibt Fehler, weil die const Qualifier in const ref error nur ignoriert, weil 8.3.2/1 sagt

Cv-qualified references are ill-formed except when the cv-qualifiers are introduced through the use of a typedef (7.1.3) or of a template type argument(14.3), in which case the cv-qualifiers are ignored.`

So errorint& nicht const int& Typ hat.

0

Dies wird zusammengestellt:

 
typedef const int& ref; 
ref error = check<int>(); 

VC++ Compiler eine Erklärung des Fehlers gibt: Qualifier Typ Referenz angewendet wird; ignoriert. Referenztyp muss als Konstante deklariert werden, const kann nicht später angewendet werden.

8

Es ist ein sehr häufiger Fehler für Englisch sprechende Leute, wegen der Art, wie die englische Grammatik funktioniert.

Ich halte es für sehr bedauerlich, dass die C++ Syntax würde beide erlauben:

const int // immutable int 
int const // immutable int 

die gleiche Bedeutung zu haben.

Es ist nicht leichter macht, wirklich, und ist nicht zusammensetzbare seit:

const int* // mutable pointer to immutable int 
int* const // immutable pointer to mutable int 

sicher nicht die gleiche Bedeutung haben.

Und das, leider für Sie, was tritt hier ein, wie @GMan erklärt.

Wenn Sie diese Art von Fehler in Zukunft vermeiden möchten, nehmen Sie die Gewohnheit, Ihre Art von Qualifikation (const und volatile) auf ihren rechts, dann werden Sie in der Lage sein, eine typedef als einfacher Text Ersatz zu behandeln.

3

Um die Konsistenz mit der Right Left Rule beizubehalten, bevorzuge ich 'cv' Qualifier wie folgt.

In Ihrem Beispiel würde ich const ref error = check<int>(); wie so

ref const error = check<int>(); // parsed as error is a const reference to an integer 

Als @Prasoon Saurav wies darauf hin, cv-Qualifikation werden ignoriert schreiben, wenn durch typedef eingeführt, weil als @GMan sagt auch, dass cv qualifizierte Referenzen sind schlecht geformt.

Daher ist die Deklaration effektiv wie unten, was natürlich ein Fehler ist.

int &error = check<int>(); 

Weitere Informationen finden Sie unter this.

+1

Dies verdient einen +1 wegen der Links in der Post gegeben. –