2010-03-15 19 views

Répondre

0

Si vous souhaitez exposer votre classe à des clients, ne forcez pas l'utilisation de pointeurs partagés. Ils savent qu'ils créent un objet et ils sont responsables de sa suppression.

Ils ont ensuite facilement peuvent écrire

myfavorite::api::shared_ptr<Class> object(Class::create()); 

ou

std::auto_ptr<Class> object(Class::create()); 
3

Si vous ne tenez pas sur des copies de celui-ci, mais vous voulez que l'utilisateur de supprimer la pointe à l'aide de l'objet delete alors vous pouvez retourner un std::auto_ptr par valeur. Il n'ajoute aucune dépendance (auto_ptr fait partie de la norme) et il fait en sorte que votre interface communique clairement l'exigence selon laquelle l'objet doit être delete d.

Si l'utilisateur le souhaite, il peut release pointer et faire les choses manuellement ou le déplacer dans son cadre de pointeur intelligent partagé.

+1

+1 J'ai oublié de mentionner dans ma réponse l'importance de l'interface aidant à la sémantique: 'auto_ptr' implique le transfert de propriété. –

+0

auto_ptr est mauvais, surtout quand vous les passez par inadvertance par valeur ... boost :: scoped_ptr est beaucoup mieux à cet égard. –

+2

@Alexandre C .: Pour cette utilisation, boost :: scoped_ptr' est totalement inapproprié. Comme il n'est pas copiable, il ne peut même pas être utilisé comme valeur de retour. 'std :: auto_ptr' n'est pas mal de la même manière qu'une tronçonneuse n'est pas mauvaise. Ce ne sont que des outils; ils n'ont aucune intention.Juste parce que jongler avec des tronçonneuses est très dangereux ne signifie pas qu'ils n'ont pas une application utile: couper les arbres. Il existe de meilleures manières standard d'exprimer le transfert de propriété en C++ 0x (par exemple unique_ptr - bien que la meilleure interface soit seulement possible grâce aux références rvalue), mais au moins 'std :: auto_ptr' est ici présent. –

2

L'élément est-il réellement partagé? C'est-à-dire, après la création, gardez-vous un pointeur dans l'objet à vos propres fins ou faites-vous cela juste pour éviter les fuites de mémoire de l'utilisateur?

Si la mémoire n'est pas réellement partagée, je n'utiliserais pas shared_ptr. Notez qu'en utilisant shared_ptr comme type de retour, vous forcez l'utilisation de l'allocation dynamique et d'une implémentation particulière d'un pointeur intelligent, mais en limitant l'utilisation de la pile pour votre type et d'autres types de pointeurs intelligents plus appropriés (vous ne pouvez pas extraire l'adhésion d'un pointeur partagé)

Si vous voulez vraiment vous assurer que l'appel ne sera pas une fuite (qui est, si l'utilisateur appelle votre fonction la mémoire retournée sera traitée « en quelque sorte », vous pouvez utiliser std::auto_ptr ou boost::unique_ptr (le dernier n'étant pas standard même en C++ 0x) Les deux solutions permettent au code appelant d'extraire le pointeur du pointeur intelligent et d'utiliser une approche différente de la gestion de la mémoire (même si cela peut être gênant dans certains cas)

struct type { 
    std::auto_ptr<type> create(); 
}; 
std::auto_ptr<type> ap = type::create(); 
std::shared_ptr<type> sp(type::create().release()); 
type::create(); // will not leak memory 
type *rp = type::create().release(); // user specifically requested a raw pointer! 
1

Cela fonctionnera, oui. Cependant, êtes-vous sûr de l'avoir besoin? Il y a des circonstances où cela est approprié, mais vous limitez vraiment vos options quand vous le faites. Il existe d'autres formes de pointeurs intelligents que les utilisateurs pourraient vouloir utiliser, sans parler du fait que vous éliminez l'allocation par pile en tant qu'option lorsque vous masquez vos constructeurs de cette façon.