2011-08-21 10 views
59

Proszę spojrzeć na poniższy prosty kodu:C++ 11 auto: co jeśli otrzyma stałe odniesienie?

class Foo 
{ 
public: 
    Foo(){} 
    ~Foo(){} 

    Foo(const Foo&){} 
    Foo& operator=(const Foo&) { return *this; } 
}; 

static Foo g_temp; 
const Foo& GetFoo() { return g_temp; } 

Próbowałem użyć auto takiego:

auto my_foo = GetFoo(); 

Spodziewałem się, że my_foo będzie stałe odniesienie do Foo, który jest powrót typ funkcji. Jednak typ auto jest Foo, a nie odniesieniem. Ponadto, my_foo jest tworzony przez kopiowanie g_temp. Takie zachowanie nie jest dla mnie oczywiste.

W celu uzyskania odniesienia do Foo, musiałem napisać tak:

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

Pytanie: Dlaczego auto wywnioskować typ zwracanej GetFoo jako przedmiot, a nie odniesienia?

+0

Z jakiego kompilatora korzystasz? –

+0

VC++ 2010 i kompilator Intel C++ – minjang

Odpowiedz

49

Przeczytaj ten artykuł: Appearing and Disappearing consts in C++


Rodzaj odliczenie dla zmiennych auto w C++ 0x jest zasadniczo taka sama jak dla parametrów szablonu. (O ile mi wiadomo, jedyną różnicą między tymi dwoma jest to, że typ zmiennych automatycznych można wywnioskować z list inicjalizujących , natomiast typy parametrów szablonu mogą nie być.) Każda z poniższych deklaracji deklaruje zmienne Typ int (nigdy const int):

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

Podczas rodzaju odliczenie dla parametrów szablonu i zmiennych auto, tylko consts najwyższego poziomu są usuwane. Biorąc pod szablon funkcji robienia parametr wskaźnika lub odniesienia, constness niezależnie od wskazanych czy mowa jest zachowana:

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 

Takie zachowanie jest stary news, stosując jak ma to miejsce zarówno C + +98 i C++ 03. Odpowiedni zachowanie zmiennych auto jest, oczywiście, nowe do 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 

Ponieważ można zachować CV-kwalifikator jeśli typ jest odniesienie lub wskaźnik, można zrobić:

auto& my_foo2 = GetFoo(); 

Zamiast określać go jako const (to samo dotyczy volatile).

Edit: Jak, dlaczego auto rozpoznaje typ zwracanej GetFoo() jako wartość zamiast odniesienia (co było głównym pytanie, przepraszam), rozważ to:

const Foo my_foo = GetFoo(); 

Powyższy stworzy kopia, ponieważ my_foo jest wartością. Jeśli auto ma zwrócić wartość odniesienia l, powyższe byłoby niemożliwe.

+5

Nie wyjaśniłeś, dlaczego zrezygnowano z kwalifikatora odwołania. –

+3

@Tomalak Geret'kal: Masz na myśli, dlaczego zdecydowali się to zrobić? Ma sens, prawda? Rozważmy to: 'Foo my_foo = GetFoo();' i że 'GetFoo()' nie zwróciło typu const. Byłoby to tak samo jak: 'auto my_foo = GetFoo();'. Jeśli auto zawiera również odniesienie, nie będziesz w stanie wykonać powyższego. – someguy

+5

Nie mów mi; umieść to w swojej odpowiedzi. –