C ++ 11 auto: cosa succede se ottiene un riferimento costante?

Si prega di dare un’occhiata al seguente codice semplice:

class Foo { public: Foo(){} ~Foo(){} Foo(const Foo&){} Foo& operator=(const Foo&) { return *this; } }; static Foo g_temp; const Foo& GetFoo() { return g_temp; } 

Ho provato ad usare auto come questo:

 auto my_foo = GetFoo(); 

Mi aspettavo che my_foo fosse un riferimento costante a Foo , che è il tipo di ritorno della funzione. Tuttavia, il tipo di auto è Foo , non il riferimento. Inoltre, my_foo viene creato copiando g_temp . Questo comportamento non è così ovvio per me.

Per ottenere il riferimento a Foo , avevo bisogno di scrivere così:

 const auto& my_foo2 = GetFoo(); auto& my_foo3 = GetFoo(); 

Domanda : Perché viene dedotto auto il tipo di ritorno di GetFoo come object, non come riferimento?

Leggi questo articolo: Apparire e sparire le consegne in C ++


La deduzione del tipo per le variabili automatiche in C ++ 0x è essenzialmente la stessa dei parametri del modello. (Per quanto ne so, l’unica differenza tra i due è che il tipo di variabili automatiche può essere dedotto dagli elenchi di inizializzatori, mentre i tipi di parametri del modello potrebbero non essere.) Ciascuna delle seguenti dichiarazioni dichiara quindi variabili di tipo int ( mai const int):

 auto a1 = i; auto a2 = ci; auto a3 = *pci; auto a4 = pcs->i; 

Durante la deduzione dei tipi per i parametri del modello e le variabili automatiche, vengono rimosse solo le versioni di livello superiore. Dato un modello di funzione che accetta un puntatore o un parametro di riferimento, viene mantenuta la costanza di qualsiasi cosa sia puntata o riferita a:

 template void f(T& p); int i; const int ci = 0; const int *pci = &i; f(i); // as before, calls f, ie, T is int f(ci); // now calls f, ie, T is const int f(*pci); // also calls f, ie, T is const int 

Questo comportamento è una vecchia notizia, che si applica a C ++ 98 e C ++ 03. Il comportamento corrispondente per le variabili automatiche è, ovviamente, nuovo a C ++ 0x:

 auto& a1 = i; // a1 is of type int& auto& a2 = ci; // a2 is of type const int& auto& a3 = *pci; // a3 is also of type const int& auto& a4 = pcs->i; // a4 is of type const int&, too 

Dato che puoi mantenere il qualificatore cv se il tipo è un riferimento o un puntatore, puoi fare:

 auto& my_foo2 = GetFoo(); 

Invece di doverlo specificare come const (lo stesso vale per volatile ).

Modifica: Per quanto riguarda il motivo per cui auto deduce il tipo di ritorno di GetFoo() come valore invece di un riferimento (che era la tua domanda principale, scusa), considera questo:

 const Foo my_foo = GetFoo(); 

Quanto sopra creerà una copia, poiché my_foo è un valore. Se auto dovesse restituire un riferimento lvalue, quanto sopra non sarebbe ansible.