2010-09-13 16 views
27

Mi chiedo se esiste il modo "più bello" di inizializzare un vettore statico rispetto al basso?Inizializzazione del vettore statico

class Foo 
{ 
    static std::vector<int> MyVector; 
    Foo() 
    { 
     if (MyVector.empty()) 
     { 
      MyVector.push_back(4); 
      MyVector.push_back(17); 
      MyVector.push_back(20); 
     } 
    } 
} 

E 'un esempio di codice :)

I valori in push_back() sono dichiarati independly; non in serie o qualcosa.

Edit: se non è possibile, mi dicono che anche :)

+3

Sarebbe interessante vedere cosa diranno i C++ 0x. Penso che qualcosa come Foo :: MyVector {4,17,20} al di fuori della definizione della classe sia possibile. –

risposta

25

In genere, ho una classe per la costruzione di contenitori che uso (come this one da spinta), in modo tale che si possono fare:

const list<int> primes = list_of(2)(3)(5)(7)(11); 

In questo modo, è possibile anche rendere statico const, per evitare modifiche accidentali.

Per una statica, si potrebbe definire questo nel file .cc:

// Foo.h 

class Foo { 
    static const vector<int> something; 
} 

// Foo.cc 

const vector<int> Foo::something = list_of(3)(5); 

In C++ Ox, avremo un meccanismo di lingua per fare questo, utilizzando le liste di inizializzazione, quindi si può solo fare:

const vector<int> primes({2, 3, 5, 7, 11}); 

Vedere here.

+0

Suppongo che se sottolinea che i valori sono "non in un array", anche la nuova funzione non andrà molto bene. Immagino che non ci sia modo di portarli in una sorta di collezione o di vivere con le ripetute chiamate di inserimento. –

+0

Penso che la lista di ciò di cui ho bisogno. Sembra semplice e, penso, più veloce di più push_backs. Quando ho detto "non sono nell'array", non ho detto che non possono essere in uno. – Xirdus

+0

Molto probabilmente, utilizza internamente più push_back() s, quindi non è "più veloce" in questo senso. Evita un condizionale nel costruttore, che lo renderebbe più veloce. Tuttavia, l'inizializzazione statica non è probabilmente quella in cui il tuo codice trascorre la maggior parte del tempo, quindi l'ottimizzazione di tali sezioni molto probabilmente non sarà un guadagno notevole. –

2

Si potrebbe provare questo:

int arr[] = { 1,2,3,4,5,6,7,8,9 }; 
MyVector.insert(MyVector.begin(), arr, &arr[sizeof(arr)/ sizeof(*arr)]); 

Ma è probabilmente vale la pena solo quando si ha un tempo molto lungo vettore, e non sembra molto bello, sia. Tuttavia, ti sei liberato delle ripetute chiamate push_back(). Naturalmente, se i tuoi valori sono "non in un array" devi prima inserirli lì, ma potresti farlo staticamente (o almeno riferimenti/puntatori), a seconda del contesto.

40

In C++ 03, il modo più semplice è stato quello di utilizzare una funzione di fabbrica:

std::vector<int> MakeVector() 
{ 
    std::vector v; 
    v.push_back(4); 
    v.push_back(17); 
    v.push_back(20); 
    return v; 
} 

std::vector Foo::MyVector = MakeVector(); // can be const if you like 

"ottimizzazione valore di ritorno" dovrebbe significare che la matrice è riempita in atto, e non copiato, se questo è un preoccupazione. In alternativa, è possibile inizializzare da un array:

int a[] = {4,17,20}; 
std::vector Foo::MyVector(a, a + (sizeof a/sizeof a[0])); 

Se non ti dispiace utilizzando una libreria non standard, è possibile utilizzare Boost.Assignment:

#include <boost/assign/list_of.hpp> 

std::vector Foo::MyVector = boost::list_of(4,17,20); 

In C++ 11 o successivo , è possibile utilizzare l'inizializzazione del brace:

std::vector Foo::MyVector = {4,17,20}; 
+2

+1 per le nuove funzionalità della lingua (sintassi di inizializzazione uniforme ftw). – rubenvb

+0

Questa funzione è una cattiva idea perché ci sarà un solo vettore statico da riempire. – Xirdus

+0

@Xirdus: cosa lo rende una cattiva idea? Se hai bisogno di inizializzare un array non vuoto, allora questo è un modo per farlo. –

1

Come inizializzare utilizzando un oggetto statico. Nel suo constatore lo potrebbe chiamare una funzione statica nell'oggetto per eseguire l'initalizzazione.

+4

Si prega di elaborare o dare un esempio. –

+0

crea una dichiarazione di classe con solo un costruttore, in cui si spinge un valore (o più valori) nel vettore globale/statico. Quindi crea un'istanza statica di quella classe -> il costruttore verrà chiamato prima di main, e verrà popolato il vettore statico. L'istanza non porrà alcun overhead di memoria in quanto non contiene alcuna variabile membro. (usa uno spazio dei nomi senza nome nel tuo file cpp per dichiarare/definire/istanziare la classe helper) –

15

Con C++ 11:

std::vector<int> Foo::MyVector = {4, 17, 20}; 
0

con boost è possibile utilizzare l'operatore + =() definito nel boost :: assegnare spazio dei nomi.

#include <boost/assign.hpp> 

using namespace boost::assign; 

int main() 
{ 
    static std::vector<int> MyVector; 
    MyVector += 4,17,20; 
    return 0; 
} 

o con l'inizializzazione statica:

#include <boost/assign.hpp> 

using namespace boost::assign; 

static std::vector<int> myVector = list_of(4)(17)(2); 

int main() 
{ 
    return 0; 
} 

o, meglio ancora, se il compilatore C++ supporta 11, liste uso di inizializzazione.

+0

Posso fare questo membro 'static' della classe? – ThomasMcLeod

+0

C++ 11 dispone di elenchi di inizializzazione per questo, oppure è possibile utilizzare strutture anziché classi e inizializzarle staticamente MyStruct val = {1, 2, 3}. Altrimenti, per i membri della classe privata, dovresti usare un costruttore. –