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.
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.
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 .
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 > >
vector<MyInteger> foo(10, MyInteger(MY_INT_VALUE));
MyFunClass(int size, int myIntegerValue) : myVector(size, MyInteger(myIntegerValue)) {};
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