Concevoir un nouveau système à partir de zéro. J'utiliserai la STL pour stocker des listes et des cartes de certains objets de longue durée.
Question: Dois-je m'assurer que mes objets ont des constructeurs de copie et stockent des copies d'objets dans mes conteneurs STL, ou est-il généralement préférable de gérer la vie et la portée moi-même et de simplement stocker les pointeurs vers ces objets dans mes conteneurs STL?
Je me rends compte que c'est un peu court sur les détails, mais je cherche la meilleure réponse «théorique» si elle existe, car je sais que ces deux solutions sont possibles.
Deux inconvénients très évidents à jouer avec les pointeurs: 1) Je dois gérer moi-même l'allocation / la désallocation de ces objets dans un périmètre au-delà de la STL. 2) Je ne peux pas créer un objet temporaire sur la pile et l'ajouter à mes conteneurs.
Y a-t-il autre chose qui me manque?
Réponses:
Étant donné que les gens s'interrogent sur l'efficacité de l'utilisation des pointeurs.
Si vous envisagez d'utiliser un std :: vector et si les mises à jour sont peu nombreuses et que vous parcourez souvent votre collection et que c'est un type non polymorphe, stocker des "copies" d'objets sera plus efficace car vous obtiendrez une meilleure localité de référence.
Otoh, si les mises à jour sont courantes, les pointeurs de stockage permettront d'économiser les coûts de copie / déplacement.
la source
Cela dépend vraiment de votre situation.
Si vos objets sont petits et que faire une copie de l'objet est léger, le stockage des données dans un conteneur stl est simple et plus facile à gérer à mon avis, car vous n'avez pas à vous soucier de la gestion de la durée de vie.
Si vos objets sont volumineux et que le fait d'avoir un constructeur par défaut n'a pas de sens, ou si les copies d'objets coûtent cher, le stockage avec des pointeurs est probablement la solution.
Si vous décidez d'utiliser des pointeurs vers des objets, jetez un œil à la bibliothèque de conteneurs Boost Pointer . Cette bibliothèque d'amplification enveloppe tous les conteneurs STL pour une utilisation avec des objets alloués dynamiquement.
Chaque conteneur de pointeur (par exemple ptr_vector) prend possession d'un objet lorsqu'il est ajouté au conteneur et gère la durée de vie de ces objets pour vous. Vous accédez également à tous les éléments d'un conteneur ptr_ par référence. Cela vous permet de faire des choses comme
Ces classes encapsulent les conteneurs STL et fonctionnent avec tous les algorithmes STL, ce qui est vraiment pratique.
Il existe également des fonctionnalités permettant de transférer la propriété d'un pointeur dans le conteneur à l'appelant (via la fonction de libération dans la plupart des conteneurs).
la source
Si vous stockez des objets polymporhiques, vous devez toujours utiliser une collection de pointeurs de classe de base.
C'est-à-dire que si vous prévoyez de stocker différents types dérivés dans votre collection, vous devez stocker des pointeurs ou vous faire manger par le démon tranchant.
la source
Désolé de sauter dans 3 ans après l'événement, mais une mise en garde ici ...
Sur mon dernier gros projet, ma structure de données centrale était un ensemble d'objets assez simples. Environ un an après le début du projet, au fur et à mesure que les exigences évoluaient, j'ai réalisé que l'objet devait en fait être polymorphe. Il a fallu quelques semaines de chirurgie cérébrale difficile et désagréable pour corriger la structure des données en un ensemble de pointeurs de classe de base et pour gérer tous les dommages collatéraux lors du stockage d'objets, du casting, etc. Il m'a fallu quelques mois pour me convaincre que le nouveau code fonctionnait. Incidemment, cela m'a fait réfléchir sérieusement à la qualité du modèle objet de C ++.
Sur mon grand projet actuel, ma structure de données centrale est un ensemble d'objets assez simples. Environ un an après le début du projet (ce qui se trouve être aujourd'hui), j'ai réalisé que l'objet devait en fait être polymorphe. De retour sur le net, j'ai trouvé ce fil de discussion et trouvé le lien de Nick vers la bibliothèque de conteneurs de pointeurs Boost. C'est exactement ce que j'ai dû écrire la dernière fois pour tout réparer, alors je vais essayer cette fois-ci.
La morale, pour moi, en tout cas: si vos spécifications ne sont pas à 100% gravées dans le marbre, optez pour des pointeurs, et vous pourriez potentiellement vous épargner beaucoup de travail plus tard.
la source
Pourquoi ne pas tirer le meilleur parti des deux mondes: faites un conteneur de pointeurs intelligents (comme
boost::shared_ptr
oustd::shared_ptr
). Vous n'avez pas à gérer la mémoire et vous n'avez pas à gérer des opérations de copie volumineuses.la source
En règle générale, le stockage des objets directement dans le conteneur STL est préférable car il est le plus simple, le plus efficace et le plus facile à utiliser.
Si votre objet lui-même a une syntaxe non copiable ou est un type de base abstrait, vous devrez stocker des pointeurs (le plus simple est d'utiliser shared_ptr)
la source
Vous semblez bien comprendre la différence. Si les objets sont petits et faciles à copier, stockez-les par tous les moyens.
Sinon, je penserais à stocker des pointeurs intelligents (pas auto_ptr, un pointeur intelligent de comptage de références) à ceux que vous allouez sur le tas. Évidemment, si vous optez pour des pointeurs intelligents, vous ne pouvez pas stocker les objets alloués à la pile temporaire (comme vous l'avez dit).
@ Torbjörn fait un bon point sur le tranchage.
la source
one
àanother
libérera la référence deone
et changeraone
.L'utilisation de pointeurs sera plus efficace car les conteneurs ne copieront que des pointeurs autour plutôt que des objets complets.
Vous trouverez ici des informations utiles sur les conteneurs STL et les pointeurs intelligents:
Pourquoi est-il incorrect d'utiliser std :: auto_ptr <> avec des conteneurs standard?
la source
Si les objets doivent être référencés ailleurs dans le code, stockez-les dans un vecteur de boost :: shared_ptr. Cela garantit que les pointeurs vers l'objet resteront valides si vous redimensionnez le vecteur.
C'est à dire:
Si personne d'autre ne stocke les pointeurs vers les objets, ou si la liste ne s'agrandit pas et ne diminue pas, stockez simplement comme des objets anciens:
la source
Cette question me dérange depuis un moment.
Je me penche sur le stockage des pointeurs, mais j'ai des exigences supplémentaires (enveloppes SWIG lua) qui pourraient ne pas s'appliquer à vous.
Le point le plus important de cet article est de le tester vous - même , en utilisant vos objets
Je l'ai fait aujourd'hui pour tester la vitesse d'appel d'une fonction membre sur une collection de 10 millions d'objets, 500 fois.
La fonction met à jour x et y en fonction de xdir et ydir (toutes les variables de membre flottant).
J'ai utilisé un std :: list pour contenir les deux types d'objets, et j'ai trouvé que stocker l'objet dans la liste est légèrement plus rapide que d'utiliser un pointeur. D'un autre côté, les performances étaient très proches, donc cela dépend de la façon dont elles seront utilisées dans votre application.
Pour référence, avec -O3 sur mon matériel, les pointeurs ont pris 41 secondes pour se terminer et les objets bruts ont pris 30 secondes pour se terminer.
la source