Décider de ce pointeur intelligent à utiliser est une question de propriété. Quand il s'agit de la gestion des ressources, l'objet A est propriétaire de l'objet B si elle est dans le contrôle de la durée de vie de l'objet B. Par exemple, les variables de membre sont la propriété de leurs objets respectifs, car la durée de vie des variables de membre est liée à la durée de vie de l'objet. Vous choisissez des pointeurs intelligents basés sur la façon dont l'objet est la propriété.
Notez que la propriété dans un système de logiciel est séparée de la propriété que nous pensons de lui en dehors du logiciel. Par exemple, une personne pourrait "propre" de leur maison, mais cela ne veut pas nécessairement dire que l' Person
objet a le contrôle sur la durée de vie d'un House
objet. L'amalgame entre ces monde réel concepts avec le logiciel de concepts est un moyen infaillible pour programmer vous-même dans un trou.
Si vous avez l'entière propriété de l'objet, utilisez std::unique_ptr<T>
.
Si vous avez partagé la propriété de l'objet...
- Si il n'y a pas de cycles dans la propriété, l'utilisation std::shared_ptr<T>
.
- Si il y a des cycles, de définir une "direction" et de l'utiliser std::shared_ptr<T>
dans un sens et std::weak_ptr<T>
dans l'autre.
Si l'objet possède vous, mais il est possible de ne pas avoir de propriétaire, de l'utilisation normale des pointeurs T*
(des parents, par exemple les pointeurs).
Si l'objet possède vous (ou sinon a garanti l'existence), utiliser des références T&
.
Mise en garde: prendre en compte le coût des pointeurs intelligents. Dans la mémoire ou les performances limitées des environnements, il pourrait être bénéfique à juste normal d'utilisation de pointeurs avec un manuel du système de gestion de la mémoire.
Les coûts:
- Si vous avez une coutume deleter (par exemple, vous utilisez l'allocation des piscines), alors cela entraînera des frais généraux par pointeur qui peut être facilement évitée par la suppression manuelle.
-
std::shared_ptr
a l'aide d'un compteur de référence de l'incrément sur la copie, en plus d'une diminution de la destruction suivi d'un 0-comte vérifier avec la suppression de l'objet. En fonction de la mise en œuvre, ce qui peut gonfler votre code et provoquer des problèmes de performances.
- Moment de la compilation. Comme avec tous les modèles, des pointeurs intelligents contribuent négativement à des temps de compilation.
Exemples:
struct BinaryTree
{
Tree* m_parent;
std::unique_ptr<BinaryTree> m_children[2]; // or use std::array...
};
Un arbre binaire n'est pas propriétaire de son parent, mais l'existence d'un arbre implique l'existence de ses parents (ou nullptr
pour les racines), de sorte qu'utilise un pointeur normal. Un arbre binaire (avec la valeur sémantique) est la propriété exclusive de ses enfants, de sorte que ceux-ci sont std::unique_ptr
.
struct ListNode
{
std::shared_ptr<ListNode> m_next;
std::weak_ptr<ListNode> m_prev;
};
Ici, la liste nœud possède son prochain et listes précédentes, nous avons donc définir une direction et d'utilisation shared_ptr
pour la prochaine et weak_ptr
pour les prev de briser le cycle.