web-dev-qa-db-fra.com

C ++ 11 auto: que se passe-t-il s'il obtient une référence constante?

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?

69
minjang

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.

61
someguy