2010-09-13 6 views
27

Ich frage mich, ob es einen "netteren" Weg zur Initialisierung eines statischen Vektors als unten gibt?Initialisierung des statischen Vektors

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

Es ist ein Beispielcode :)

Die Werte in push_back() sind independly erklärt; nicht in Array oder etwas.

Edit: wenn es nicht möglich ist, sagt mir, dass auch :)

+3

Würde mich interessieren, was die C++ 0x Leute sagen werden. Ich denke, etwas wie Foo :: MyVector {4,17,20} außerhalb der Klassendefinition ist möglich. –

Antwort

25

Normalerweise Ich habe eine Klasse für Behälter konstruieren, die ich (wie this one von Boost) verwenden, so dass Sie tun können:

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

auf diese Weise können Sie die statische const sowie machen, um eine versehentliche Änderungen zu vermeiden.

Für einen statischen, können Sie diese in der .cc-Datei definieren:

// Foo.h 

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

// Foo.cc 

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

In C++ Ox, wir werden eine Sprache Mechanismus, dies zu tun haben, initializer Listen verwenden, so können Sie einfach tun:

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

here See.

+0

Ich denke, wenn er betont, dass die Werte "nicht in einem Array" sind, dann wird die neue Funktion auch nicht viel nutzen. Ich denke, es gibt keinen Weg, sie in irgendeine Art von Sammlung zu bringen oder mit den wiederholten Einführungsrufen zu leben. –

+0

Ich denke, list_of ist was ich brauche. Es sieht einfach aus und, glaube ich, schneller als mehrere Pushbacks. Als ich sagte "sie sind nicht in einer Reihe", habe ich nicht erwähnt, dass sie nicht in einem sein können. – Xirdus

+0

Wahrscheinlich verwendet es intern mehrere push_back() s, also ist es in diesem Sinne nicht "schneller". Es vermeidet eine Bedingung im Konstruktor, die das schneller machen würde. Die statische Initialisierung ist jedoch wahrscheinlich nicht der Ort, an dem der Code die meiste Zeit verbringt. Daher ist die Optimierung dieser Abschnitte höchstwahrscheinlich kein merklicher Gewinngewinn. –

2

Sie könnten versuchen, diese ein:

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

Aber es ist wahrscheinlich nur lohnt, wenn Sie einen wirklich langen Vektor haben, und es sieht nicht viel besser aus, auch nicht. Sie werden jedoch die wiederholten push_back() Aufrufe los. Wenn Ihre Werte "nicht in einem Array" sind, müssten Sie sie natürlich zuerst dort einfügen, aber Sie könnten dies statisch (oder zumindest Referenzen/Zeiger) tun, abhängig vom Kontext.

40

In C++ 03, war der einfachste Weg, eine Fabrik-Funktion:

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 

„Optimierung Rückgabewertes“, dass das Array an Ort und Stelle gefüllt ist, bedeuten sollte, und nicht kopiert, wenn das a Besorgnis, Sorge. Alternativ können Sie aus einem Array initialisieren:

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

Wenn Sie nichts dagegen haben eine Nicht-Standard-Bibliothek verwenden, können Sie Boost.Assignment verwenden:

#include <boost/assign/list_of.hpp> 

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

In C++ 11 oder höher können Sie Klammerinitialisierung verwenden:

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

+1 für neue Sprachfunktionen (uniform initialization syntax ftw). – rubenvb

+0

Diese Funktion ist eine schlechte Idee, da nur ein statischer Vektor zu füllen ist. – Xirdus

+0

@Xirdus: Was macht es eine schlechte Idee? Wenn Sie ein nicht leeres Array initialisieren müssen, ist dies eine Möglichkeit. –

1

Wie über Initialisierung mit einem statischen Objekt. In seinem Konstruktor könnte eine statische Funktion in dem Objekt aufrufen, um die Initalisierung durchzuführen.

+4

Bitte erläutern oder geben Sie ein Beispiel. –

+0

Erstellen Sie eine Klassendeklaration mit nur einem Konstruktor, wobei Sie einen Wert (oder mehrere Werte) in den globalen/statischen Vektor zurückschieben. Erstellen Sie dann eine statische Instanz dieser Klasse -> der Konstruktor wird vor main aufgerufen und der statische Vektor wird aufgefüllt. Die Instanz wird keinen Speicheraufwand verursachen, da sie keine Mitgliedsvariablen enthält. (Verwenden Sie einen unbenannten Namespace in Ihrer cpp-Datei, um die Hilfsklasse zu deklarieren/definieren/zu instanziieren) –

15

Mit C++ 11:

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

mit Boost Sie den + = Operator() in der boost verwenden können :: Namespace zuweisen.

#include <boost/assign.hpp> 

using namespace boost::assign; 

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

oder mit statischer Initialisierung:

#include <boost/assign.hpp> 

using namespace boost::assign; 

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

int main() 
{ 
    return 0; 
} 

oder noch besser, wenn Ihr Compiler C 11 ++ unterstützt, Listen Verwendung der Initialisierung.

+0

Kann ich diese 'statischen' Klassenmitglieder machen? – ThomasMcLeod

+0

C++ 11 hat Initialisierungslisten dafür, oder Sie könnten Strukturen anstelle von Klassen verwenden und sie statisch initialisieren MyStruct val = {1, 2, 3}. Andernfalls müssten Sie für private Klassenmitglieder einen Konstruktor verwenden. –