Veuillez consulter le code simple suivant:
class Foo
{
public:
Foo(){}
~Foo(){}
Foo(const Foo&){}
Foo& operator=(const Foo&) { return *this; }
};
static Foo g_temp;
const Foo& GetFoo() { return g_temp; }
J'ai essayé d'utiliser auto
comme ceci:
auto my_foo = GetFoo();
Je m'attendais à ce que my_foo
sera une référence constante à Foo
, qui est le type de retour de la fonction. Cependant, le type de auto
est Foo
, pas la référence. En outre, my_foo
est créé en copiant g_temp
. Ce comportement n'est pas si évident pour moi.
Afin d'obtenir la référence à Foo
, j'avais besoin d'écrire comme ceci:
const auto& my_foo2 = GetFoo();
auto& my_foo3 = GetFoo();
Question: Pourquoi auto
déduit-il le type de retour de GetFoo
comme objet, pas comme référence?
Lisez cet article: Constantes apparaissant et disparaissant en C++
La déduction de type pour les variables automatiques en C++ 0x est essentiellement la même que pour les paramètres de modèle. (Pour autant que je sache, la seule différence entre les deux est que le type de variables automatiques peut être déduit des listes d'initialisation, tandis que les types de paramètres de modèle peuvent ne pas l'être.) Chacune des déclarations suivantes déclare donc des variables de type int ( jamais const int):
auto a1 = i;
auto a2 = ci;
auto a3 = *pci;
auto a4 = pcs->i;
Lors de la déduction de type pour les paramètres de modèle et les variables automatiques, seules les consts de niveau supérieur sont supprimées. Étant donné un modèle de fonction prenant un pointeur ou un paramètre de référence, la constance de tout ce qui est pointé ou référencé est conservée:
template<typename T>
void f(T& p);
int i;
const int ci = 0;
const int *pci = &i;
f(i); // as before, calls f<int>, i.e., T is int
f(ci); // now calls f<const int>, i.e., T is const int
f(*pci); // also calls f<const int>, i.e., T is const int
Ce comportement est une ancienne nouvelle, s'appliquant comme il le fait à la fois à C++ 98 et C++ 03. Le comportement correspondant pour les variables automatiques est, bien sûr, nouveau pour 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
Puisque vous pouvez conserver le qualificatif cv si le type est une référence ou un pointeur, vous pouvez faire:
auto& my_foo2 = GetFoo();
Au lieu d'avoir à le spécifier comme const
(il en va de même pour volatile
).
Edit: Quant à savoir pourquoi auto
déduit le type de retour de GetFoo()
comme une valeur au lieu d'une référence (qui était votre question principale, désolé), considérez ceci:
const Foo my_foo = GetFoo();
Ce qui précède créera une copie, car my_foo
Est une valeur. Si auto
devait renvoyer une référence lvalue, ce qui précède ne serait pas possible.