2013-08-18 13 views
9

Właśnie zadałem dwa pytania dotyczące inicjalizacji tablic i wartości here i here. Ale z tym kodem, gubię:Dlaczego std :: array <int, 10> x nie jest inicjalizowany od zera, ale std :: array <int, 10> x = std :: array <int, 10>() wydaje się być?

#include <iostream> 
#include <iomanip> 
#include <array> 

template <class T, class U = decltype(std::declval<T>().at(0))> 
inline U f1(const unsigned int i) 
{T x; return x.at(i);} 

template <class T, class U = decltype(std::declval<T>().at(0))> 
inline U f2(const unsigned int i) 
{T x = T(); return x.at(i);} 

int main() 
{ 
    static const unsigned int n = 10; 
    static const unsigned int w = 20; 
    for (unsigned int i = 0; i < n; ++i) { 
     std::cout<<std::setw(w)<<i; 
     std::cout<<std::setw(w)<<f1<std::array<int, n>>(i); 
     std::cout<<std::setw(w)<<f2<std::array<int, n>>(i); 
     std::cout<<std::setw(w)<<std::endl; 
    } 
    return 0; 
} 

Zgodnie z oczekiwaniami, f1 powrócić arbitralne wartości, jak jej wartości nie są zero-zainicjowany. Ale f2 wydaje się powrócić wyłącznie zerowej wartości:

    0     0     0 
        1     61     0 
        2     0     0 
        3     0     0 
        4   297887440     0 
        5    32767     0 
        6    4196848     0 
        7     0     0 
        8   297887664     0 
        9    32767     0 

Osobiście myślałem, że f2 utworzy tablicę z dowolnych wartości i kopiuj/przenieś go do x. Ale wydaje się, że tak nie jest.

Tak, mam dwa pytania:

  • Dlaczego?
  • Czy C++ 11 std::array<T, N> i C-style T[N] mają takie samo zachowanie w takiej sytuacji?
+3

'T()' jest zainicjowanym wartością 'T'. Niepoprawna składnia, jeśli 'T' jest tablicą typu C. 'T x = {};' lub 'T x {};' to bardziej ogólnie stosowane składnie. – Casey

+0

@ Inicjalizacja wartości krytycznej dotyczy macierzy w stylu C. 'T()' jest błędem składni, jeśli 'T' nie jest specyfikatorem typu prostego, tj. Pojedynczym identyfikatorem lub słowem kluczowym, które określa typ. W C++ 03 '= {}' dotyczy tylko tablic, a prosty '{}' jest błędem. – Potatoswatter

+0

Przypuszczalny duplikat dotyczy inicjowania wartości, ale to pytanie dotyczy domyślnej inicjalizacji. Otwórz ponownie i znajdź odpowiedni duplikat lub po prostu odpowiedz. – Potatoswatter

Odpowiedz

9

Korzystanie {} lub () jako inicjatora, z naszymi bez = skutkuje inicjalizacji wartości. W przypadku typu z niejawnie deklarowanym konstruktorem inicjowanie wartości implementuje zerową inicjalizację, która jak sama nazwa wskazuje ustawia każdy prymitywny element na 0. Dzieje się tak, zanim konstruktor może zostać uruchomiony, ale w tym przypadku konstruktor nic nie robi.

Ponieważ konstruktor nie robi nic (to jest banalna), można zobaczyć niezainicjowane dane.

Podobnie jak w przypadku macierzy w stylu C, zachowanie jest podobne, jeśli zamiast = T() użyje się = {}, ponieważ jest on nielegalny. T() prosi o tymczasowy obiekt tablicy, który zostanie przypisany do nazwanego obiektu, ale tablic nie można przypisać. = {} z drugiej strony przypisuje do tablicy tabliczną listę inicjatora wzmacnianego, a lista z ustalonym inicjatorem jest specjalną konstrukcją składniową, która nie jest ani wyrażeniem, ani obiektem.

Powiązane problemy