2017-01-27 3 views
2

Quelqu'un pourrait-il expliquer simplement la raison pour laquelle cela ne fonctionne pas:pointeur partagé et vie pointeur brut

std::shared_pointer<Bar> getSharedPointer() { 
    return std::make_shared<Bar>(); 
} 

... 

auto foo = getSharedPointer().get(); 

Apparemment en utilisant le pointeur brut foo provoque une erreur de segmentation, car la durée de vie du pointeur partagé retourné par getSharedPointer() aura s'épuiser. D'une manière ou d'une autre, je m'attendrais à ce qu'il dure jusqu'à la fin de sa portée (comme n'importe quel bloc à l'intérieur).

Est-ce correct et existe-t-il des exemples analogues à cette situation?

+1

Vous ne trouvez pas 'getSharedPointer' documentés dans la bibliothèque standard ou tiers communs parties. Aucune idée de ce qui se passe. Recommande d'ajouter un peu plus d'informations. – user4581301

Répondre

7

Pour getSharedPointer().get();, getSharedPointer() renvoie un std::shared_ptr temporaire qui sera détruit immédiatement après l'expression, et le pointeur géré par celui-ci sera également supprimé. Après que foo deviendra pendule, n'importe quelle déréférence sur elle provoque UB.

auto foo = getSharedPointer().get(); 
// foo have become dangled from here 

Vous pouvez utiliser une variable nommée à la place:

auto spb = getSharedPointer(); 
auto foo = spb.get(); 
// It's fine to use foo now, but still need to note its lifetime 
// because spb will be destroyed when get out of its scope 
// and the pointer being managed will be deleted too 
+0

s'il vous plaît, ajoutez une note que 'spb' ne durera que jusqu'à la fin de la portée –

1
auto foo = getSharedPointer().get(); 

Chaque fois qu'une fonction retourne un type qui n'est pas une référence, le résultat de l'appel de la fonction est un rvalue. En outre, étant donné que la fonction getSharedPointer() renvoie un type de classe, le résultat est un objet temporaire.

La durée de vie de cet objet temporaire est définie comme la fin de l'évaluation de l'expression la plus externe, ici getSharedPointer().get(). Dès que la variable foo est initialisée, le pointeur intelligent propriétaire est détruit; Lorsque le dernier shared_ptr possédant cet objet est détruit, l'objet est supprimé.

Ici getSharedPointer() retourne toujours shared_ptr qui ne partage pas l'objet géré (use_count() est 1), de sorte que lorsque cette copie de la dernière shared_ptr est détruite, l'objet est détruit et le pointeur sur l'objet est invalide.

(Je ne sais pas pourquoi vous retournez un shared_ptr et non un unique_ptr ici.)

L'utilisation correcte d'un pointeur intelligent, ou toute classe qui « possède » (contrôle la durée de vie) d'autres ressources (ressources auxquelles vous êtes toujours autorisé à accéder directement), est de garder le pointeur/propriétaire "intelligent" en vie aussi longtemps que vous avez besoin d'accéder à la ressource.

Le pointeur "intelligent" (objet propriétaire) doit donc être nommé. Aussi, je ne suis pas sûr que vous voudriez vraiment cacher le fait que c'est un pointeur intelligent de la vue du lecteur avec auto.

std::shared_pointer<Bar> foo = getSharedPointer(); 
// use foo.get() 

Vous pouvez cacher le type exact d'objet géré:

std::shared_pointer<auto> foo = getSharedPointer(); 
+0

de se référer à nouveau au code pour voir si un ptr unique a plus de sens dans l'application, mais merci pour les heads up; Je vérifierai. Aussi, vous avez expliqué exactement ce que j'avais besoin de savoir sur les objets temporaires et les vies, ce qui a échoué à m'éduquer sur le fait d'être néophyte avec cpp. Merci. – tau