Perché std::array<int, 10> x non è inizializzata a zero, ma std::array<int, 10> x = std::array<int, 10>() sembra essere?

Ho appena fatto due domande su array e il valore di inizializzazione qui e qui.
Ma con questo codice, mi sono perso:

#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;
}

Come previsto, f1 restituire valori arbitrari come i suoi valori non sono inizializzata a zero. Ma f2 sembra di tornare esclusivamente i valori zero:

                   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

Personalmente ho pensato che f2 creazione di un array con i valori arbitrari e copiare/spostare x. Ma non sembra essere il caso.

Così, ho due domande:

  • Perché?
  • Fare in C++11 std::array<T, N> e C-stile T[N] hanno lo stesso comportamento in tale situazione?
  • T() è un valore inizializzato T. E di sintassi non valida se T è un tipo C tipo di matrice. T x = {}; o T x{}; sono più generalmente applicabile sintassi.
  • valore di inizializzazione si applica a C gli array stile. T() è un errore di sintassi se T non è un semplice tipo identificatore, cioè un identificatore unico o una parola chiave che il nome di un tipo. In C++03, = {} si applica solo per le matrici e semplice {} è un errore.
  • Il presunto duplicato è di circa il valore di inizializzazione, ma questa domanda è di circa default di inizializzazione. Si prega di riaprire e trovare un giusto duplicati, o semplicemente la risposta.
  • Io non suggeriscono che il valore di inizializzazione non si applica a C gli array stile. Un semplice tipo identificatore può anche essere di tipo nome (tra cui un typedef nome) o un semplice modello-id. La domanda è su C++11.
  • Nota che 5.2.3/2 definisce funzionale-cast notazione: “L’espressione T(), dove T è un semplice tipo identificatore o typename identificatore per un camere non-array completa tipo di oggetto o l’ (possibilmente cv qualificato) void tipo, crea un prvalue del tipo specificato,che è valore inizializzato (8.5; nessuna inizializzazione è fatto per il void() caso).” Si proibisce esplicitamente i tipi di matrice.
  • Va bene. Anche se non proibisce che si può avere un prvalue di tipo array e matrici non sono CopyConstructible, così T x = T() non avrebbe funzionato. Anyhoo, questo è foraggio per una risposta, e la domanda originale (perché di default-inizializzazione di una classe come std::array lascia i suoi membri non inizializzato) rimane irrisolta.
  • La domanda era “perché sintassi zero questa matrice quando sintassi B non?” Ho sentito che la mia affermazione circa la sintassi era sufficiente per differenziare le due, dato che ci sono stati molto esaurienti discussioni su inizializzazione di default vs valore di inizializzazione nelle risposte a Vincent sono due domande precedenti (1) (2).
  • std::array<T, N> è più come il C stile struct S {T arr[N];}; di raw T[N]. S x = S(); anche lasciare x.arr inizializzato a zero, per le ragioni esposte dai commenti precedenti.
  • Ah, (2) copre la domanda, ma non è stato precedentemente collegato da qui. (1) non. Comunque si parla di “non di classe, camere non-matrice di tipo” ma non banale constructibility, che IIRC è il vero fattore determinante. std::array è una classe, dunque, la sua confusione.

InformationsquelleAutor Vincent | 2013-08-18



One Reply
  1. 14

    Utilizzando {} o () come un inizializzatore, con o senza =, si traduce in un valore di inizializzazione. Per un tipo con un implicitamente dichiarato costruttore, il valore di inizializzazione implementa zero di inizializzazione, che come suggerisce il nome, consente di impostare ogni elemento primordiale per 0. Questo si verifica prima che il costruttore può essere eseguito, ma in questo caso, il costruttore non fa nulla.

    Poiché il costruttore non fa nulla (è banale), è possibile vedere i dati non inizializzati.

    Come per C gli array stile, il comportamento è simile se si utilizza = {} invece di = T(), in quanto quest’ultimo è illegale. T() sarebbe chiedere un array temporaneo oggetto da assegnare all’oggetto con nome, ma gli array non possono essere assegnati. = {} invece assegna un rinforzato-inizializzatore-list per l’array, e rinforzato-inizializzatore-list è una speciale costruzione sintattica, che non è né un’espressione né un oggetto.

Lascia un commento