web-dev-qa-db-fra.com

Comment initialiser un vecteur stl d'objets qui ont eux-mêmes des constructeurs non triviaux?

supposons que j'ai la classe suivante:

class MyInteger {
private:
  int n_;
public:
  MyInteger(int n) : n_(n) {};
  // MORE STUFF
};

Et supposons que cette classe n'ait pas de constructeur trivial par défaut MyInteger(). Je dois toujours fournir un int pour l'initialiser pour une raison quelconque. Et puis supposez que quelque part dans mon code j'ai besoin d'un vector<MyInteger>. Comment initialiser chaque MyInteger composant dans ce vector<>?

J'ai deux situations (probablement la solution est la même, mais je vais quand même les énoncer), une variable normale à l'intérieur d'une fonction:

int main(){
    vector<MyInteger> foo(10);  //how do I initialize each 
                                //MyInteger field of this vector? 
    doStuff(foo);
}

et comme données dans une classe:

class MyFunClass {
private:
   vector<MyInteger> myVector;

public:
   MyFunClass(int size, int myIntegerValue) : myVector(size) {}; 
   // what do I put here if I need the 
   // initialization to call MyInteger(myIntegerValue) for all 
   // components of myVector?
};

Est-il possible de le faire uniquement dans la liste d'initialisation ou dois-je écrire l'initialisation à la main dans le constructeur MyFunClass (int, int)?

Cela semble tellement basique, et pourtant je l'ai raté dans mon livre et je ne le trouve pas sur le Web.

31

Il y a plusieurs façons de s'y rendre. En voici quelques-unes (sans ordre de présence particulier).

Utilisez le constructeur vector(size_type n, const T& t). Il initialise le vecteur avec n copies de t. Par exemple:

#include <vector>

struct MyInt
{
    int value;
    MyInt (int value) : value (value) {}
};

struct MyStuff
{
    std::vector<MyInt> values;

    MyStuff () : values (10, MyInt (20))
    {
    }
};

Poussez les éléments dans le vecteur un par un. Cela peut être utile lorsque les valeurs doivent être différentes. Par exemple:

#include <vector>

struct MyInt
{
    int value;
    MyInt (int value) : value (value) {}
};

struct MyStuff
{
    std::vector<MyInt> values;

    MyStuff () : values ()
    {
        values.reserve (10); // Reserve memory not to allocate it 10 times...
        for (int i = 0; i < 10; ++i)
        {
            values.Push_back (MyInt (i));
        }
    }
};

Une autre option est la liste d'initialisation du constructeur, si C++ 0x est une option:

#include <vector>

struct MyInt
{
    int value;
    MyInt (int value) : value (value) {}
};

struct MyStuff
{
    std::vector<MyInt> values;

    MyStuff () : values ({ MyInt (1), MyInt (2), MyInt (3) /* ... */})
    {
    }
};

Bien sûr, il existe une option pour fournir un constructeur par défaut et/ou utiliser autre chose que std::vector.

J'espère que cela aide.

30
user405725

Si les éléments du vecteur ne sont pas constructibles par défaut, il y a certaines choses que vous ne pouvez pas faire avec le vecteur. Vous ne pouvez pas écrire ceci (exemple 1):

vector<MyInteger> foo(10);

Vous pouvez cependant écrire ceci (exemple 2):

vector<MyInteger> foo(10, MyInteger(37));

(Cela ne nécessite qu'un constructeur de copie.) Le deuxième argument est un initialiseur pour les éléments du vecteur.

Dans votre cas, vous pouvez également écrire:

vector<MyInteger> foo(10, 37);

... puisque MyInteger a un constructeur non explicite prenant "int" comme argument. Le compilateur va donc transtyper 37 en MyInteger (37) et donner le même résultat que l'exemple 2.

Vous voudrez peut-être étudier la documentation sur std :: vector .

11
Nemo

Outre toutes les réponses qui ont très bien répondu à la question, dans le cas où votre classe MyInteger n'est pas copiable, vous pouvez utiliser cette astuce: au lieu de créer vector< MyInteger>, vous pouvez créer vector< shared_ptr< MyInteger > >

6
BЈовић
vector<MyInteger> foo(10, MyInteger(MY_INT_VALUE));

MyFunClass(int size, int myIntegerValue) : myVector(size, MyInteger(myIntegerValue)) {}; 
6
mbykov

Les listes d'initialisation peuvent être utilisées sans référence aux objets sous-jacents.

#include <string>
#include <vector>
using namespace std;


class Test
{
   public:
   struct NumStr
   {
      int num;
      string str;
   };

   Test(vector<int> v1,vector<NumStr> v2) : _v1(v1),_v2(v2) {}
   vector<int> _v1;
   vector<NumStr> _v2;
};

int main()
{
   Test t={ {1,2,3}, {{1,"one"}, {2,"two"}, {3,"three"}} };
   cout << t._v1[1] << " " << t._v2[1].num << " " << t._v2[1].str << endl;
   return 0;
}

sortie: 2 2 deux

1
edW