C++: Vecteur d'objets vs. vecteur de pointeurs vers de nouveaux objets?
Je cherche à améliorer mon C++ compétences par l'écriture d'un exemple de moteur de rendu logiciel. Il prend des objets composés de points dans un espace 3d et des cartes à une fenêtre d'affichage 2d et dessine des cercles de taille variable pour chaque point de vue. Quel est le meilleur:
class World{
vector<ObjectBaseClass> object_list;
public:
void generate(){
object_list.clear();
object_list.push_back(DerivedClass1());
object_list.push_back(DerivedClass2());
ou...
class World{
vector<ObjectBaseClass*> object_list;
public:
void generate(){
object_list.clear();
object_list.push_back(new DerivedClass1());
object_list.push_back(new DerivedClass2());
?? Serait en utilisant les pointeurs dans le 2ème exemple pour créer de nouveaux objets à vaincre le point de l'utilisation de vecteurs, car les vecteurs d'appeler automatiquement le DerivedClass destructeurs dans le premier exemple, mais pas dans le 2ème? Sont des pointeurs vers de nouveaux objets nécessaires lors de l'utilisation de vecteurs en raison de gérer la mémoire de gestion eux-mêmes aussi longtemps que vous utilisez leurs méthodes d'accès? Maintenant, disons que j'ai une autre méthode dans le monde:
void drawfrom(Viewport& view){
for (unsigned int i=0;i<object_list.size();++i){
object_list.at(i).draw(view);
}
}
Lorsqu'il est appelé cela va exécuter la méthode de tirage pour chaque objet de la liste mondiale. Disons que je veux classes dérivées pour être en mesure d'avoir leurs propres versions de draw(). Serait la liste doivent être des pointeurs pour utiliser le sélecteur de la méthode (->) ?
- thnx édité pour ne pas détourner l'attention de la question
Vous devez vous connecter pour publier un commentaire.
Vous ne obtenez ce que Vous voulez avec ce code
Ce qui va se passer est appelé objet de découpage. Vous recevrez un vecteur de ObjectBaseClass.
De faire du polymorphisme de travail que Vous avez à utiliser un certain type de pointeurs. Il y a probablement un peu de smart pointeurs ou des références à d'amplifier ou d'autres bibliothèques qui peuvent être utilisés et rendre le code plus sûr que la deuxième solution proposée.
Puisque vous êtes en indiquant explicitement que vous souhaitez améliorer votre C++, je vais vous recommandons de commencer à utiliser Boost. Cela peut vous aider avec votre problème de trois façons différentes:
À l'aide d'un
shared_ptr
À l'aide d'un
shared_ptr
pourrait déclarer votre vecteur comme ceci:Et de l'utiliser comme ceci:
Ce serait vous donner le polymorphisme et serait utilisé comme un vecteur normal de pointeurs, mais le
shared_ptr
ferait la gestion de la mémoire pour vous, en détruisant l'objet lors de la dernièreshared_ptr
référencement, il est détruit.Remarque à propos de C++11: En C++11
shared_ptr
est devenu une partie de la norme commestd::shared_ptr
, afin de Booster n'est plus nécessaire pour cette approche. Cependant, à moins que vous vraiment besoin de la copropriété, il est recommandé de les utiliserstd::unique_ptr
, qui a été introduit récemment dans C++11.À l'aide d'un
ptr_vector
À l'aide d'un
ptr_vector
vous serait de faire comme ceci:Et de l'utiliser comme ceci:
Ce serait à nouveau être utilisé comme un vecteur normal de pointeurs, mais cette fois, la
ptr_vector
gère la durée de vie de vos objets. La différence de la première approche est, qu'ici, vos objets sont détruits lorsque le vecteur est détruit, tandis qu'au-dessus, ils peuvent vivre plus longtemps que le conteneur, si d'autresshared_ptr
s de référencement existent.À l'aide d'un
reference_wrapper
À l'aide d'un
reference_wrapper
vous déclarer comme ceci:Et ensuite l'utiliser comme ceci:
Remarquez que vous n'avez pas à déréférencer l'itérateur d'abord comme dans les approches ci-dessus. Cela ne fonctionne que si la durée de vie de vos objets est gérée ailleurs et il est garanti d'être plus longue que celle de la
vector
.Remarque à propos de C++11:
reference_wrapper
a également été normalisés en C++11 et est maintenant utilisable commestd::reference_wrapper
sans Boost.Comme l'a souligné dans Maciej Hs réponse, votre première approche des résultats en objet de découpage. En général, vous voudrez peut-être chercher dans les itérateurs lors de l'utilisation de conteneurs.
shared_ptr
dans unvector
peut être incroyablement mauvais en fonction des opérations que vous effectuez. D'habitude, je le recommandeptr_vector
.Que pour votre première question, il est généralement préférable d'utiliser attribués automatiquement les objets plutôt que les objets alloués dynamiquement (en d'autres termes, pas pour stocker des pointeurs), de sorte que le type en question, la copie de la construction et de l'affectation est possible et pas trop cher.
Si les objets ne peuvent pas être copiés ou attribués, alors vous ne pouvez pas les mettre directement dans un
std::vector
de toute façon, et la question est donc sans objet. Si la copie et/ou des opérations d'affectation sont coûteux (par exemple, l'objet stocke une grande quantité de données), alors vous pourriez vouloir stocker des pointeurs pour des raisons d'efficacité. Sinon, il est généralement préférable de ne pas stocker des pointeurs exactement pour la raison que vous avez mentionné (automatique désallocation)Quant à votre deuxième question, oui, c'est une autre raison valable pour stocker des pointeurs. Répartition dynamique (méthode virtuelle appels) de ne travailler que sur les pointeurs et les références (et vous ne pouvez pas stocker les références dans un
std::vector
). Si vous avez besoin de stocker des objets de plusieurs types polymorphes dans le même vecteur, vous doit stocker des pointeurs afin d'éviter de trancher.Eh bien, cela dépend de ce que vous essayez de faire avec votre vecteur.
Si vous n'utilisez pas de pointeurs, alors c'est un copie de l'objet que vous transmettez qui est mis sur le vecteur. Si c'est un simple objet, et/ou vous ne voulez pas vous embêter à faire le suivi de stockage pour eux, cela peut être exactement ce que vous voulez. Si c'est quelque chose de complexe, ou beaucoup de temps pour construire et détruire, vous préférerez peut-être faire le travail qu'une seule fois chacun et de passer des pointeurs dans le vecteur.