2009-04-25 11 views
7

Je veux pouvoir initialiser un vecteur de taille 'SIZE' avant main. Normalement, je neInitialisation d'un vecteur avant main() en C++

static vector<int> myVector(4,100); 

int main() { 

    // Here I have a vector of size 4 with all the entries equal to 100 

} 

Mais le problème est que je voudrais initialiser le premier élément du vecteur d'être d'une certaine valeur, et l'autre à une autre valeur.

Y at-il un moyen facile de faire cela?

+0

Que dire celle-ci: std :: vecteur un (3, 100), et a_init ((a [0] = 98, a [1] = 99, a)); il va faire un égal à "98, 99, 100" :) –

+1

Juste par curiosité, pourquoi avez-vous besoin? –

Répondre

6

est ici solution de rechange :

#include <vector>     
static std::vector<int> myVector(4,100); 

bool init() 
{ 
    myVector[0] = 42;  
    return true; 
} 

bool initresult = init(); 

int main()     
{ 
    ; 
} 
+0

Intéressant ... Est-il possible de ne pas gaspiller l'espace booléen? – Unknown

+0

Oui, mais pas vraiment. vous pourriez essayer d'incorporer l'initcall quelque part, mais cela le "cacherait": int somevalue = (init(), 42); –

+0

Notez également que static est déprécié en tant que notificateur pour la liaison "interne" (c'est-à-dire uniquement dans l'unité de traduction). Utilisez plutôt un espace de noms anonyme. – Macke

20

Essayez ceci:

static int init[] = { 1, 2, 3 }; 
static vector<int> vi(init, init + sizeof init/sizeof init[ 0 ]); 

Aussi, voir std::generate (si vous voulez initialiser dans une fonction).

+1

Ce n'est pas seulement le moyen le plus évident, mais aussi le moyen le plus rapide et le plus clair. +1 (au moins si les autres éléments sont tous à zéro) –

+0

non, cela donnera un vecteur 3 éléments (pas d'éléments supplémentaires), mais pour cela, c'est plutôt soigné. – Macke

7

Un peu hackish, mais vous pouvez le faire:

struct MyInitializer { 
    MyInitializer() { 
     myVector[0]=100; 
     //... 
    } 
} myInitializer; // This object gets constructed before main() 
+0

hackish, et un peu dangereux parce que vous ne pouvez pas attraper des exceptions avant la main, mais exactement ce que je fais dans ces cas aussi. –

+0

@Nils: En fait, la classe vectorielle fournit un ctor basé sur l'itérateur qui peut être couplé avec des tableaux pour ce genre de chose. Beaucoup plus sûr, OMI. – dirkgently

9

Ou tout simplement créer une fonction et appeler:

std::vector<int> init() 
{ 
    ... 
} 

static std::vector<int> myvec = init() 

Un peu inefficace peut-être, mais cela pourrait ne pas d'importance pour vous, et avec C++ 0x et le déplacer sera très rapide.

Si vous voulez éviter la copie (pour 03 C++ et plus tôt), utiliser un pointeur intelligent:

std::vector<int>* init() { 
    return new std::vector<int>(42); 
} 

static boost::scoped_ptr<std::vector<int>> myvec(init()); 
0

l'envelopper par une classe:

class SpecialVector 
{ 
    public: 
    SpecialVector() 
    { 
     myVector[0] = 1; 
     myVector[1] = 4; 
     // etc. 
    } 
    const vector<int> & GetVector() const 
    { 
     return myVector; 
    } 
    private: 
    vector<int> myVector; 
}; 
static SpecialVector SpVec; 

int main() { 
} 
+0

pourquoi pourquoi pourquoi ..... –

+0

global statique est mauvais .... a-les annuler si vous le pouvez! aucun moyen d'attraper l'exception, valgrind pense qu'il s'agit d'une fuite, difficile à déboguer s'il y a une exception à la sortie de l'application! –

9

C++ 0x permettra listes initialiseur pour conteneurs standard, tout comme les agrégats:

std::vector<int> bottles_of_beer_on_the_wall = {100, 99, 98, 97}; 

De toute évidence pas encore standard, mais il est supposé être pris en charge par GCC 4.4. Je ne peux pas trouver de documentation à ce sujet dans MSVC, mais Herb Sutter a dit que leur support C++ 0x est devant le comité ...

3

Plutôt que d'utiliser un global, je dirais qu'il est préférable d'utiliser un statique locale. Comme l'initialisation de votre vecteur a lieu avant que le principal ne soit entré, aucune exception ne sera interceptée par main. Disons, par exemple, vous avez un type qui, lorsqu'il est construit peut jeter une exception:

class A { 
public: 
    A() { 
    // ... code that might throw an exception 
    } 
}; 

Pour l'initialisation suivante, le try/catch dans le corps principal ne sera pas attraper l'exception lancée par le constructeur, et ainsi votre Le programme va simplement mourir immédiatement et vous ne pourrez probablement même pas utiliser un débogueur pour trouver la cause!

std::Vector<A> v(5, A()); // May throw an exception here not caught by main 

int main() { 
    try { 
    // Exception for 'v' not handled here. 
    } 
    catch (...) { 
    } 
} 

Une autre approche qui va attraper une exception du constructeur est d'utiliser une statique locale - qui est initialisé en utilisant la technique proposée par ce answer.

std::Vector<A> init(); // Returns a vector appropriately initialized 

std::vector<A> & getV() { 
    static std::vector<A> cache = init(); 
    return cache; 
} 

int main() { 
    try { 
    getV().at[0]; // First call to getV - so initialization occurs here! 
    } 
    catch (...) { 
    } 
} 
Questions connexes