Supprimer std :: shared_ptr sans détruire l’object géré?

Je suis dans le scénario suivant:

struct container { data* ptr; }; void someFunc(container* receiver /* wants to be filled */) { auto myData = createData(); // returns shared_ptr receiver->ptr = myData.get(); } 

La fonction qui génère ces données et l’object qui les reçoit font partie de deux bibliothèques différentes, pour lesquelles je ne peux pas modifier le code source. Je dois travailler avec ces types de données, je ne peux rien y faire.

Je dois donc implémenter une fonction qui acquiert des données, puis transmet un pointeur à ces données vers un object. Mon problème est que la fonction qui crée mes données, lui renvoie une instance shared_ptr . L’object qui a besoin des données acceptera uniquement un pointeur brut.

Comme vous pouvez le constater, j’appelle get() sur shared_ptr pour obtenir le pointeur brut et le transmettre à l’object récepteur. Si je ne me trompe pas, alors shared_ptr décrémente le nombre de références chaque fois qu’il sort de la scope. Donc, dans ce cas, cela signifie que mes données seront détruites dès le retour de la fonction, car le nombre de références atteindra 0.

Alors, comment puis-je me débarrasser de l’instance shared_ptr sans détruire l’object géré? L’object auquel je transmets les données (illustré par la structure “container” pour plus de simplicité) prend en charge le nettoyage de la mémoire à l’intérieur de son destructeur, je n’ai donc besoin d’aucun décompte de références ni de choses du genre. Je ne veux plus rien surveiller les données allouées (à l’exception de l’object qui reçoit un pointeur dessus). Je souhaite supprimer le shared_ptr et ne disposer que d’un pointeur brut sur les données allouées, que je peux transmettre à l’object récepteur.

Est-ce possible?

 static std::map m >; struct container { data* ptr; }; void someFunc(container* receiver /* wants to be filled */) { auto myData = createData(); // returns shared_ptr, I can't do anything about it receiver->ptr = myData.get(); m[receiver->ptr] = myData; } void someOtherFunc(container* receiver) { // delete receiver->ptr; m.erase(receiver->ptr); } 

Cela prolonge la vie de shared_ptr travers une carte.

std::shared_ptr n’abandonne pas la propriété, vous devez donc la conserver quelque part dans votre classe pour vous assurer que le pointeur ne sera pas supprimé. Néanmoins, vous pouvez utiliser le shared_ptr acquis au lieu de stocker le pointeur brut. Les pointeurs bruts sont presque toujours un mauvais choix.

Ce n’est pas possible.

Même si vous vous occupez de la destruction des objects dans le destructeur de container , vous ne pouvez garantir qu’aucun autre object ne possède le pointeur conservant std::shared_ptr sur cet object (dans ce cas, vous verrez une double free erreur double free ).

Si la durée de vie d’un object est gérée par std::shared_ptr (sans suppression spéciale), vous ne pouvez contrôler la durée de vie d’un object que via std::shared_ptr et std::weak_ptr .

La seule façon pour moi de voir cela (si votre conception le permet) consiste à envelopper votre conteneur:

 struct container { data* ptr; }; struct container_wrapper { std::shared_ptr ptr; // ensure this lives as long as needed container cnt; }; void someFunc(container_wrapper& receiver /* wants to be filled */) { receiver.ptr = createData(); receiver.cnt.ptr = receiver.ptr.get(); }