2012-01-31 23 views
12

Mi piacerebbe utilizzare std::array da C++ 11 come un campo della mia stessa classe. Richiede due parametri del modello (prima definisce il tipo di dati, il secondo definisce le dimensioni di un array).C++ 11 std :: array

Ma conosco il secondo parametro solo nel costruttore. Non ho familiarità con lo standard C++ 11, ma suppongo che sia impossibile impostare un parametro template durante l'esecuzione.

Esistono alternative per std::array? std::vector è probabilmente un po 'troppo, perché non cambierò mai la dimensione di esso.

risposta

15

std::vector è la cosa più semplice da utilizzare; anche se come dici tu, spreca pochi byte se non avrai mai bisogno di ridimensionarlo.

std::unique_ptr<T[]>, inizializzato utilizzando il risultato di new T[size], sarebbe la cosa più efficiente; dovrebbe avere le stesse dimensioni di un puntatore e cancellerà la memoria allocata per te quando viene distrutta. Non è copiato, però; dovrai fornire un costruttore di copie per la tua classe se vuoi che sia possibile copiarlo. È anche meno conveniente di std::array e std::vector, poiché non ha l'interfaccia di un contenitore standard. Potresti forse scrivere un wrapper in stile STL per questo se ne hai bisogno; ma dovrei semplicemente usare std::vector in questo caso.

+3

Direi di usare uno std :: vector su un unique_ptr , il primo è compatibile con tutte le funzioni di libreria standard che funzionano sugli iteratori. In effetti, l'intero punto di std :: array è di fornire tale interfaccia su un array normale. –

+3

@ user1131467: Infatti, 'std :: vector' è molto più conveniente; ma l'OP ha espresso preoccupazione per l'efficienza, quindi forse è importante salvare pochi byte. –

+0

Se stai per scrivere un wrapper in stile STL, almeno dovrebbe conoscere anche la sua dimensione. Non puoi preoccuparti solo della capacità. – UncleBens

6

std :: array è per quando si conosce la dimensione staticamente in fase di compilazione. Se non conosci fino al runtime, usa un vettore std ::. Se non lo ridimensionate, non c'è molto sovraccarico.

class Container 
{ 
    vector<T> v; 
    Container(int i) : v(i) { v.shrink_to_fit(); } 
}; 

Se siete preoccupati per lo spazio:

http://en.cppreference.com/w/cpp/container/vector/shrink_to_fit

Non sono sicuro se c'è un modo per costruire il vettore già trimed. Non sembra richiesto dallo standard di essere rifinito, anche se in pratica molte implementazioni lo faranno.

BTW È inoltre possibile costruire un vettore con vettore (size_t N, T t) che imposterà ogni elemento iniziale su t (senza che gli elementi siano predefiniti).

+0

IIRC, il vettore è costruito con * esattamente * la capacità richiesta. Non c'è bisogno di restringere in seguito.Anche il trucco copy-and-swap per rimpicciolire un vettore si basa su questo. – Xeo

+1

È interessante notare che, per alcuni benchmark, non vi è alcun sovraccarico e il codice 'std :: vector' restituisce lo stesso codice SSE vettorizzato come con gli array nativi (con g ++ almeno) –

+0

Penso che un array sia allocato sul posto e un il vettore è assegnato dinamicamente. –

11

Non ho familiarità con lo standard C++ 11, ma suppongo che sia impossibile impostare un parametro template durante l'esecuzione.

Non è possibile passare un valore noto solo in fase di esecuzione come argomento modello ... il codice creato da un'istanza di modello deve essere creato in fase di compilazione, pertanto non può dipendere da un valore di runtime.

Alcune soluzioni possibili sono la creazione di specializzazioni di modello per alcuni valori di dimensione di matrice comuni e quindi un possibile valore di dimensione massima. Penso che sarebbe un modo piuttosto inefficiente di lavorare.

Per essere onesti, nella vostra situazione, un std::vector sarebbe molto probabilmente la soluzione migliore perché si può semplicemente chiamare resize() sul vettore per rendere la dimensione corretta in fase di esecuzione attraverso l'allocazione dinamica.

+1

oppure, invece di 'resize()', usa il costruttore 'std :: vector (size_t n)'. –

+2

@phresnel: o 'reserve' + una sequenza di' push_back'/'emplace_back' se non tutti gli elementi devono essere uguali. –

3

Se non si conosce la dimensione dell'array fino al momento dell'esecuzione, si desidera utilizzare un vettore std ::.

Problemi correlati