49 votes

Une mauvaise pratique de retour unique_ptr pour pointeur brut comme la propriété de la sémantique?

J'ai écrit un statique usine méthode qui renvoie une nouvelle Foobar objet rempli à partir d'un autre objet de données. J'ai récemment été obsédé par la sémantique de propriété et je me demande si je vais transmettre le message à droite en ayant cette méthode de fabrique, de retour d'un unique_ptr.

class Foobar {
public:
    static unique_ptr<Foobar> factory(DataObject data);
}

Mon intention est-à-dire le code de client qu'ils possèdent le pointeur. Sans un pointeur intelligent, je voudrais simplement revenir Foobar*. Je tiens, cependant, à faire valoir que cette mémoire soit supprimé afin d'éviter d'éventuels bugs, donc, unique_ptr a semblé comme une solution appropriée. Si le client souhaite prolonger la durée de vie du pointeur, ils appelez - .release() une fois qu'ils obtiennent l' unique_ptr.

Foobar* myFoo = Foobar::factory(data).release();

Ma question est livré en deux parties:

  1. Cette approche transmettre la propriété correcte de la sémantique?
  2. Est-ce une "mauvaise pratique" pour retourner à l' unique_ptr au lieu d'un pointeur brut?

60voto

Grizzly Points 11329

Retour d'un std::unique_ptr à partir d'une méthode de fabrique est très bien et devrait être une pratique recommandée. Le message qu'elle véhicule est (OMI): Vous êtes désormais le seul propriétaire de cet objet. De plus, pour votre confort, l'objet ne sait comment détruire lui-même.

Je pense que c'est beaucoup mieux que de retourner un pointeur brut (où le client a rappeler comment et si pour se débarrasser de ce pointeur).

Cependant, je ne comprends pas votre commentaire à propos de libérer le pointeur de prolonger sa durée de vie. En général, j'ai rarement vu aucune raison d'appeler à l' release sur un smartpointer, car je pense que les pointeurs devraient toujours être gérés par une sorte de RAII de la structure (à peu près la seule situation où je m'appelle release est de mettre le pointeur dans une autre gestion de discbased, par exemple, un unique_ptr avec un autre deleter, après j'ai fait quelque chose pour justifier de nettoyage supplémentaires) .

Par conséquent, le client peut (et doit), il suffit de stocker l' unique_ptr quelque part (comme un autre unique_ptr, qui a été déplacer construit à partir de l'retourné une) tant qu'ils ont besoin de l'objet (ou d' shared_ptr, s'ils ont besoin de plusieurs copies du pointeur). Si le client le code devrait ressembler à ceci:

std::unique_ptr<FooBar> myFoo = Foobar::factory(data);
//or:
std::shared_ptr<FooBar> myFoo = Foobar::factory(data);

Personnellement, je voudrais également ajouter un typedef pour le retour de type pointeur (dans ce cas - std::unique_ptr<Foobar>) et ou la deleter (dans ce cas, std::default_deleter) à votre usine de l'objet. Cela rend plus facile si vous décidez plus tard de modifier la répartition de votre pointeur(et donc besoin d'une méthode différente pour la destruction du pointeur, qui sera visible en tant que second paramètre de modèle de std::unique_ptr). Donc, je voudrais faire quelque chose comme ceci:

class Foobar {
public:  
    typedef std::default_deleter<Foobar>     deleter;
    typedef std::unique_ptr<Foobar, deleter> unique_ptr;

    static unique_ptr factory(DataObject data);
}

Foobar::unique_ptr myFoo = Foobar::factory(data);
//or:
std::shared_ptr<Foobar> myFoo = Foobar::factory(data);

17voto

James McNellis Points 193607

Un std::unique_ptr unique propriétaire de l'objet vers lequel il pointe. Il dit "je suis propriétaire de cet objet, et personne d'autre ne le fait."

C'est exactement ce que vous essayez d'exprimer: vous dites "appelant de cette fonction: vous êtes désormais le seul propriétaire de cet objet; faire avec elle comme vous s'il vous plaît, sa durée de vie est de votre responsabilité."

6voto

Dietmar Kühl Points 70604

Exactement exprime la sémantique correcte et je crois que toutes les usines en C++ devrait fonctionner: std::unique_ptr<T> n'impose pas de tout type de propriété sémantique et il est extrêmement bon marché.

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