52 votes

pimpl: shared_ptr ou unique_ptr

J'ai fait quelques objets à l'aide de la pimpl idiome, mais je ne sais pas si utilisé std::shared_ptr ou std::unique_ptr.

Je comprends unique_ptr est plus efficace, mais ce n'est pas tellement un problème pour moi, car ces objets sont relativement lourds, de sorte que les coûts d' std::shared_ptr sur std::unique_ptr est relativement mineur.

Je suis actuellement en cours avec std::shared_ptr seulement en raison de la plus grande flexibilité d'utilisation. Par exemple, à l'aide d'un std::shared_ptr me permet de stocker ces objets à-dire une table de hachage pour un accès rapide tout en étant capable de retourner les copies de ces objets pour les appelants (comme je le crois, tout itérateurs ou références peuvent rapidement devenir invalide).

Cependant, ces objets ne sont vraiment pas être copié, que les modifications portent sur l'ensemble des copies, donc je me demandais que peut-être l'aide d' std::shared_ptr et permettant des copies est une sorte d'anti-modèle ou une mauvaise chose.

Toutes les pensées?

37voto

Matthieu M. Points 101624

J'ai fait quelques objets à l'aide de la pimpl idiome, mais je ne sais pas si utilisé shared_ptr ou unique_ptr.

Définitivement unique_ptr ou scoped_ptr.

Pimpl n'est pas un modèle, mais un idiome, qui traite de la compilation de la dépendance du temps et de la compatibilité binaire. Il ne devrait pas affecter la sémantique des objets, en particulier en ce qui concerne sa copie de comportement.

Vous pouvez utiliser n'importe quel type de pointeur intelligent que vous voulez sous le capot, mais ces 2 la garantie que vous ne serez pas accidentellement partager la mise en œuvre entre deux objets distincts, car ils nécessitent une décision consciente à propos de la mise en œuvre du constructeur de copie et l'opérateur d'affectation.

Cependant, ces objets ne sont vraiment pas être copié, que les modifications portent sur l'ensemble des copies, donc je me demandais que peut-être l'aide d' shared_ptr et permettant des copies est une sorte d'anti-modèle ou une mauvaise chose.

Il n'est pas un anti-modèle, en fait, il s'agit d'un modèle: l'Aliasing. Vous utilisez déjà, en C++, avec les pointeurs et références. shared_ptr offrent une mesure de "sécurité" pour éviter les morts références, au coût supplémentaire de complexité et de nouvelles questions (attention aux cycles de créer des fuites de mémoire).


Sans rapport avec Pimpl

Je comprends unique_ptr est plus efficace, mais ce n'est pas tellement un problème pour moi, car ces objets sont relativement lourds, de sorte que les coûts d' shared_ptr sur unique_ptr est relativement mineur.

Si vous pouvez tenir compte de l'état, vous pouvez prendre un coup d'oeil à la Mouche modèle.

11voto

James Kanze Points 96599

Si vous utilisez shared_ptr, ce n'est pas vraiment le classique pimpl idiome (à moins que vous prendre des mesures supplémentaires). Mais la vraie question c'est pourquoi vous voulez utiliser un pointeur intelligent pour commencer; c'est très clair où l' delete devrait se produire, et il n'y a pas de problème de exception de sécurité ou d'autres à être concernés par. Tout au plus, un pointeur intelligent vous permettra d'économiser en une ou deux lignes de code. Et la seul à la sémantique correcte est - boost::scoped_ptr, et je ne pense pas que cela fonctionne dans ce cas. (IIRC, il nécessite un type complètes pour être instancié, mais je pourrais être mal.)

Un aspect important de la pimpl idiome est que son utilisation devrait être transparent pour le client; la classe doit se comporter exactement comme si il ont été mises en œuvre de façon classique. Cela signifie soit en inhibant la copie et de la cession ou de la mise en œuvre de copie en profondeur, à moins que la classe est immuable (pas de non-const fonctions de membre). Aucun d'habitude pointeurs intelligents mettre en œuvre copie en profondeur; vous pourriez mettre en œuvre, de bien sûr, mais il serait sans doute encore besoin d'une complète type chaque fois que la copie se passe, ce qui signifie que vous auriez toujours se fournir à un utilisateur défini constructeur de copie et l'opérateur d'affectation (puisqu'ils ne peuvent pas être en ligne). Compte tenu de cela, il n'est probablement pas vaut la peine en utilisant le pointeur intelligent.

Une exception est si les objets sont immuables. Dans ce cas, il n'a pas d'importance si la copie est profonde ou pas, et shared_ptr les poignées de la situation complètement.

5voto

Nim Points 22570

Lorsque vous utilisez un shared_ptr (par exemple dans un récipient, puis de regarder cela et le retourner par valeur), vous ne sont pas la cause d'une copie de l'objet et il points de, simplement une copie du pointeur avec un nombre de références.

Cela signifie que si vous modifiez l'objet sous-jacent à partir de plusieurs points, alors vous influer sur les changements sur la même instance. C'est exactement ce qu'il est conçu, donc pas un anti-modèle!

N'oubliez pas, cependant, toujours passer et retour par valeur plutôt que la référence!

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X