2010-07-04 4 views
4

Disons que j'ai une classe FOO. Je veux un std::vector de FOO.Laquelle de ces pratiques est la meilleure?

Est-il mieux si je fais quelque chose comme ceci:

FOO foo; 
foo.init(); 
foo.prop = 1; 
std::vector<FOO> myvec; 

myvec.push_back(foo); 
foo.prop = 2; 
myvect.push_back(foo); 

ou est-il une meilleure pratique de le faire:

std::vector<FOO> myvec; 
FOO foo; 
myvec.push_back(foo); 
myvec.back().init(); 
myvec.back().prop = 1; 

myvec.push_back(foo); 
myvec.back().init(); 
myvec.back().prop = 2; 

Je suis fondamentalement pas sûr de son mieux pour faire un modèle et pousser le modèle au lieu de faire une instance, le pousser, puis le modifier à partir du vecteur. Aussi, lequel est le plus sûr et le moins susceptible de provoquer des fuites de mémoire?

Merci

+5

Pourquoi Foo :: Foo() n'invoque pas Foo :: init()? Cela peut être utile si vous postez une classe Foo concrète. –

+0

Les fuites de mémoire ne se produiront pas à moins que vous n'utilisiez de nouveau sans supprimer. –

Répondre

8

Aucune de ces méthodes ne présente de problèmes de mémoire car vous traitez des valeurs et n'allouez pas d'objets manuellement de manière dynamique.

Je préférerais donner FOO un constructeur qui fait quoi que ce soit init et fixe prop à la valeur appropriée. Ensuite, vous pouvez simplement pousser les valeurs que vous souhaitez:

myvec.push_back(FOO(1)); 
myvec.push_back(FOO(2)); 
10

Les meilleures pratiques est de ne pas avoir une fonction init() - vous voulez un constructeur. Si vous avez toujours besoin de définir prop, donnez au constructeur un paramètre pour le faire. Cela n'a rien à voir avec les vecteurs - c'est la façon dont tout le code C++ devrait être écrit.

1

Je pense que le mieux est de:

myvec.push_back(FOO(1)); 
myvec.push_back(FOO(2)); 
1

La réponse dépend de ce que fait votre classe FOO. Si c'est une structure simple sans pointeurs etc., alors vos deux approches sont bien et font la même chose.

Notez que push_back insère un copie de l'objet dans le vecteur. Si votre classe alloue de la mémoire sur le tas, vous avez besoin d'un constructeur de copie qui crée une copie complète de vos objets, sinon vous vous retrouverez avec des fuites de mémoire. En outre, si vos objets sont assez volumineux, il peut s'avérer inefficace de créer des copies. Dans ce cas, ce que je fais en général est d'allouer l'objet lui-même sur le tas à l'extérieur et insérez le pointeur dans le vecteur:

std::vector<FOO *> myvec; 
FOO *foo; 

foo = new FOO(); 
foo->init(); 
foo->val = 1; 
myvec.push_back(foo); 

foo = new FOO(); 
foo->init(); 
foo->val = 2; 
myvec.push_back(foo); 

Cependant, dans ce cas, vous devez vous rappeler de libérer les objets avant de détruire le vecteur .

0

Outre ce que les autres ont dit au sujet de l'initialisation de vos objets dans le constructeur, je voudrais ajouter ceci:

Dans votre deuxième exemple, où vous mettez des objets dans le vecteur, puis de les initialiser, vous risquez de laisser votre vecteur dans un état inutilisable.

Si par exemple, la méthode init() peut lancer une exception, vous aurez un objet non/partiellement initialisé dans votre vecteur.

Bien sûr, ces problèmes disparaissent avec un constructeur qui s'assure que les objets sont correctement initialisés.

En général: Ne commencez pas à faire des choses avec des objets avant qu'ils ne soient dans un état utilisable.

Questions connexes