2013-06-12 24 views
5

Uczę się C++ 11 i natknąłem się na jednolitych inicjalizatorów.Większość irytujących parse zamieszania

Nie rozumiem następujący kod, który powinien pokazać „najbardziej dokuczliwy składniowy” dwuznaczność:

#include<iostream> 


class Timer 
{ 
public: 
    Timer() {} 
}; 

int main() 
{ 

    auto dv = Timer(); // What is Timer() ? And what type is dv? 

    int time_keeper(Timer()); // This is a function right? And why isn't the argument " Timer (*)()" ? 



    return 0; 
} 
+0

AFAIK, druga linia wywołuje MVP, pierwsza nie. –

+0

Wiem o tym, ale jestem mylić z typami zaangażowanymi w kod –

Odpowiedz

9

tutaj:

auto dv = Timer(); 

masz obiekt typu Timer nazywa dv czyli inicjowane podczas kopii z tymczasowego (wyrażenie po prawej stronie znaku =).

Podczas deklarowania zmiennej za pomocą auto, typ tej zmiennej jest taki sam, jak typ wyrażenia, które ją inicjalizuje - nie biorąc pod uwagę tutaj kwalifikatorów i odniesień cv.

W twoim przypadku wyrażenie, które inicjuje dv ma typ Timer, a więc dv ma typ Timer.

tutaj:

int time_keeper(Timer()); 

zadeklarować funkcję o nazwie time_keeper która zwraca int i bierze za swoje wejście do wskaźnik do funkcji, która zwraca Timer i nie bierze argument.

Dlaczego nie ma argumentu: Timer (*)()?

Funkcje rozpad do wskaźników gdy przekazany jako argument, więc rodzaj time_keeper jest rzeczywiście int(Timer(*)()).

Aby przekonać się, można spróbować kompilacji ten mały program:

#include <type_traits> 

struct Timer { }; 
int main() 
{ 
    int time_keeper(Timer()); 
    static_assert(
     std::is_same< 
      decltype(time_keeper), 
      int(Timer(*)()) 
     >::value, 
     "This should not fire!"); 
} 

Oto live example.

+0

Dzięki, czy argument nie powinien być "Timer (*)()"? Czy "Timer()" jest również dopuszczalnym wskaźnikiem funkcji? –

+1

Przypuszczam, że tak jest w przypadku 'functionName' i' & functionName' będącego tym samym. – Spook

+0

@DavidKernin: Funkcje automatycznie zanikają do wskaźników, gdy są używane jako argumenty funkcji, więc 'void (Timer())' i 'void (Timer (*)())' są identycznymi typami. –

-4

wszystko tutaj jest dobre, za każdym razem dostajesz instancję Timera.

za to być deklaracja funkcja musi mieć postać

Timer name(); 

w tym przypadku nie wystąpienia niczego poprawnej składni w tym przypadku są:

Timer name; 
+0

-1: Nie, nie jest dobrze. 'time_keeper' jest funkcją. Który zwraca 'int' i przyjmuje argument typu niejawnie-zepsutego-wskaźnika-do funkcji-biorących-bez-argumentów-i-powracających-Timera. – Angew