2010-09-27 9 views
15

Ho sentito che gli oggetti temporanei possono essere assegnati solo a riferimenti costanti.riferimenti costanti con typedef e modelli in C++

Ma questo codice di errore dà

#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; 
} 

L'errore che è ottenere è invalid initialization of reference of type 'int&' from expression of type 'const int'

risposta

21

questo:

typedef int& ref; 
const ref error; 

non fa quello che pensi lo fa. Considerate invece:

typedef int* pointer; 
typedef const pointer const_pointer; 

Il tipo di const_pointer è int* const, nonconst int *. Cioè, quando dici const T stai dicendo "fai un tipo in cui T è immutabile"; così nell'esempio precedente, il puntatore (non il pointee) è reso immutabile.

I riferimenti non possono essere effettuati const o volatile. Questo:

int& const x; 

non ha significato, quindi l'aggiunta di qualifiche cv ai riferimenti non ha alcun effetto.

Pertanto, error ha il tipo int&. Non è possibile assegnare un const int& ad esso.


Ci sono altri problemi nel codice. Ad esempio, questo è certamente sbagliato:

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

Che cosa stai facendo qui sta tornando un riferimento a un oggetto temporaneo che termina la sua vita quando la funzione restituisce. Cioè, si ottiene un comportamento indefinito se lo si utilizza perché non vi è alcun oggetto al referente. Questo non è meglio di:

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

Una prova migliore sarebbe:

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

Il valore di ritorno della funzione è una temporanea, in modo da poter ancora provare che si può provvisori infatti si legano ai riferimenti costanti .

+0

Buona risposta. +1 :) –

+0

Grazie. :) – GManNickG

7

Il codice dà errore perché il qualificatore const in const ref error viene semplicemente ignorato perché 8.3.2/1 dice

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.`

Così error ha digitare int& non const int&.

0

Questo viene compilato:

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

VC++ compilatore dà qualche spiegazione del vostro errore: qualificatore applicato al tipo di riferimento; ignorato. Il tipo di riferimento deve essere dichiarato come costante, const non può essere applicato in seguito.

8

È un errore molto comune per le persone che parlano inglese, a causa del modo in cui la grammatica inglese funziona.

ritengo estremamente spiacevole che la sintassi del C++ permetterebbe sia:

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

avere lo stesso significato.

Non fa più facile, in realtà, e non è componibile dal:

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

certamente non hanno lo stesso significato.

E questo, sfortunatamente per voi, è quello che calcia qui, come spiega @GMan.

Se si desidera evitare questo tipo di errore in futuro, prendere l'abitudine di qualificazione i tipi di (const e volatile) sul loro destra, allora sarete in grado di trattare una semplice sostituzione del testo typedef.

3

Per mantenere la coerenza con lo Right Left Rule, preferisco utilizzare i qualificatori "cv" in questo modo.

Nel tuo esempio, vorrei scrivere const ref error = check<int>(); in questo modo

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

Come @Prasoon Saurav ha sottolineato, qualificazioni cv vengono ignorati quando introdotto attraverso typedef perché come @GMan dice anche, che i cv riferimenti qualificati sono mal formati.

Pertanto, la dichiarazione è efficace come di seguito, che ovviamente è un errore.

int &error = check<int>(); 

Verificare this per ulteriori informazioni.

+1

Questo merita un +1 a causa dei collegamenti dati nel post. –