2014-05-15 5 views
3

J'ai un objet qui est apparemment supprimé en double malgré le fait qu'il soit suivi par des pointeurs intelligents. Je suis nouveau à l'aide de pointeurs intelligents, donc j'ai fait une fonction simple pour tester si j'utilise l'objet correctement. Cet ensemble de lignes dans la fonction principale provoque une erreur d'exécution lorsque les pointeurs sortent du champ d'application, pourquoi? Les pointeurs intelligents ne sont-ils pas supposés être capables de gérer la suppression d'un par eux-mêmes?pointeur partagé double suppression

+1

Êtes-vous la suppression d'un seul? tu n'es pas censé faire ça. Utilisez make_shared au lieu d'allouer manuellement un. – Kiroxas

Répondre

0

Utilisation correcte est:

std::shared_ptr<int> b = std::make_shared<int>(2); 
std::shared_ptr<int> c = b; 
9

A shared_ptr à propre attend l'objet pointé à.

Ce que vous avez fait est de créer deux pointeurs intelligents distincts, dont chacun pense avoir la propriété exclusive du sous-jacent int. Ils ne connaissent pas l'existence de l'autre, ils ne se parlent pas. Par conséquent, quand ils sortent de la portée, les deux pointeurs suppriment la ressource sous-jacente, avec le résultat évident. Lorsque vous créez un shared_ptr, il crée une sorte d '"objet de gestion" responsable de la durée de vie de la ressource. Lorsque vous copiez un shared_ptr, les deux copies référencent le même objet de gestion. L'objet de gestion conserve la trace du nombre d'instances shared_ptr pointant sur cette ressource. Un int* en lui-même n'a pas un tel "objet de gestion", donc le copier ne garde pas de trace des références.

est ici une réécriture minimale de votre code:

// incidentally, "make_shared" is the best way to do this, but I'll leave your 
// original code intact for now. 
int *a = new int(2); 

std::shared_ptr<int> b(a); 
std::shared_ptr<int> c = b; 

Maintenant, ils ont tous deux référence au même objet de gestion sous-jacente. Comme chaque shared_ptr est détruit, le nombre de références sur le int* est réduit et lorsque la dernière référence est supprimée, l'objet est supprimé.

+0

Un meilleur style est de faire std :: shared_ptr b (new int (2)) pour éviter d'avoir un pointeur de transition a. Ayant un implique le danger de a) un être supprimé par un code aléatoire dans le champ d'application; b) fuite de mémoire lorsqu'une exception se produit avant un reach shared_ptr. Le shared_ptr est conçu pour être capable de prendre le pointeur brut et seulement du constructeur, et c'est la raison pour cela. Un moyen encore meilleur est, std :: shared_ptr b (std :: make_shared ) - make_shared n'a que 1 allocation de mémoire alors que la manière précédente a au moins deux allocations de mémoire. – h9uest

+0

@ h9uest votre point serait beaucoup plus pertinent si ce n'était pas une modification minimale du code fourni dans la question initiale. Il n'a jamais été destiné à être un exemple parfait de C++, et n'a jamais prétendu l'être. Si vous lisez le commentaire dans le bloc de code, vous verrez que 'make_shared' a été mentionné. – Rook

2

Vous êtes seulement autorisé à créer un pointeur intelligent une fois à partir d'un pointeur brut. Tous les autres pointeurs partagés doivent être des copies du premier afin qu'ils fonctionnent correctement. Mieux encore: l'utilisation faire partager:

std::shared_ptr<int> sp1 = std::make_shared<int>(2); 
std::shared_ptr<int> sp2 = sp1; 

EDIT: oublié d'ajouter le deuxième pointeur