J'ai étudié uniques_ptr et j'ai décidé d'écrire un code simple pour vous assurer que j'ai compris le concept et sur la façon de l'utiliser. Ce que j'ai ci-dessous est une classe de manager, qui a une dent qui contient uniques_ptrs. SO TEMPFONCNAME () Retournera une liste des pointeurs de base de base qui satisfait certaines conditions. J'ai à l'origine pensé à avoir le nom TempfuncName Retour une liste de documents_ptrs, mais j'ai senti que défaite tout le but d'utiliser uniques_ptrs. Donc, à la place, je reçois les pointeurs bruts de l'unique_ptr et push_back () ces pointeurs bruts dans la liste et renvoient cette liste. P> Je me demandais simplement si ce que je fais (retourner des pointeurs bruts au lieu de uniques_ptrs) est en fait une bonne pratique de codage, ou s'il est correct de simplement retourner uniques_ptrs (que je ne pense pas, c'est une bonne idée depuis) ou si je ne devais même pas utiliser uniques_ptrs dans cette situation. P> J'ai essayé de googler, mais Un grand nombre de postes que j'ai trouvés n'a pas vraiment discuté de cette question particulière. P> Toute aide et informations seraient grandement appréciées. P> p>
3 Réponses :
retourne un pointeur brut au lieu de une bonne pratique de codage unique? p> blockQuote>
non. Et oui. Il n'y a pas de réponse, car cela dépend du contexte. C'est assez simple cependant: p>
Transférer la propriété d'une ressource avec un pointeur brut est une mauvaise pratique de codage. P>
retourner un pointeur non propriétaire est une bonne pratique (bien que dans certains cas, une référence peut être meilleure). P>
Ces considérations sont vraies en général et restent vraies dans votre exemple particulier. Vous devez déterminer si vous avez l'intention de conserver les objets dans
Manager CODE> ou avez-vous l'intention de transférer la propriété à l'appelant. Vous n'avez pas supprimé les pointeurs uniques de la fonction, il semble donc que votre intention est de ne pas transférer la propriété. Sur la troisième, si vous avez l'intention de partager la propriété, vous devez utiliser des pointeurs partagés partout. P>
Passons à travers des options de ce que vous pouvez revenir p>
Si vous retournez Si vous retournez Si vous savez à coup sûr em> que ces objets existent, par exemple parce que le Si un pointeur NULL est une option valide pour revenir, vous ne pouvez pas utiliser de références, donc unique_ptr code> s, alors par définition em> ces objets ne sont plus gérés par le gestionnaire. On dirait qu'ils devraient toujours être, alors
unique_ptr code> n'est pas le bon type. P>
Shared_ptr code> s, ou
faibly_ptr code> s, alors vous pouvez être sûr que les modifications ultérieures du gestionnaire invalident soudainement vos valeurs. Soit signifier que vous modifiez la file d'attente vers
partagée_ptr code>. P>
si code> filtré nulls, il serait vraiment agréable de retourner
basoclass et Code> s. Le problème est que vous ne pouvez pas avoir une référence en tant que
valeur_type code> d'un conteneur. Dans ce cas, j'utiliserais
std :: référence_wrapper
basoclass * code> n'est pas beaucoup pire, comme
référence_wrapper code> est fondamentalement un pointeur quand même. p>
basoclass * code> peut être votre meilleure option. P>
Utilisation de brut Utilisation du pointeur d'observateur brut va bien ... mais comme le code existant peut utiliser des pointeurs de propriété brute, le pointeur brut est ambigu du pointeur d'observateur et du pointeur de possession . P> types tels que Les pointeurs d'observateurs ne possèdent pas de données, la durée de vie des données doit être plus longue que le pointeur d'observateur. P> Dans votre cas, des choix possibles Inclure: p> std :: expérimental :: Observateur_ptr
a été introduit pour exprimer clairement l'intention. (Mais c'est fondamentalement juste un pointeur). p> class Manager
{
public:
// std::function might be replaced by template for the Functor
void for_each_filtered(std::function<bool(const T&)> filter,
std::function<void(/*const*/ T&)> action) /*const*/
{
for (auto& d : data) {
if (filter(*d)) {
action(*d)
}
}
}
private:
std::vector<std::unique_ptr<T>> data;
};
Clarifier "introduit": le pointeur d'observateur a été adopté dans la spécification technique de l'extension de la bibliothèque standard; non incorporé dans le projet de la norme à venir (pourtant, et pourrait ne pas nécessairement être toujours).
Il y a des cas où seul un scalaire fera, pas une classe qui (très mal) émule un scalaire
Utilisez
unique_ptr code> pour montrer l'intention de la propriété. Pour les paramètres ou les valeurs de retour, il codifie le transfert de la propriété. Utilisez un pointeur brut pour montrer l'intention de ne pas être transférée. Pour un paramètre, un pointeur brut signifie "Cela pourrait être nullptr, ou pourrait avoir une valeur" (s'il ne peut jamais être nullptr, utilisez plutôt une référence).
Vous avez donc une situation dans laquelle vous voulez des pointeurs sur votre drique et que les mêmes pointeurs sont revenus d'une fonction de recherche. Il me semble que vous devriez utiliser
std :: partagé_ptr code> car vos pointeurs ne sont pas uniques. Mais cela dépend de la Propriété i> et Lifetime i> des pointeurs. Si les pointeurs de la drique vont toujours survivre aux pointeurs renvoyés de la fonction, vous pouvez dire que la deque possède les pointeurs, puis le code que vous avez est bon. Mais en général, je pense que j'irais pour des indications partagées dans une affaire comme celle-ci.
@John Yeah, je veux que la classe Manager soit le propriétaire des objets et aucun autre pointeurs ne peut pointer vers les objets. Je n'étais tout simplement pas sûr s'il était correct de renvoyer des pointeurs bruts puisque la classe de gestionnaire possède les objets et que le retour d'un document_ptr pourrait potentiellement provoquer le transfert de la propriété de l'endroit où la fonction est appelée.
Si la classe Manager supprimera les objets, renvoyez les pointeurs bruts (et ne les utilisez pas après la destruction de la classe Manager).
@Jamesl alors quel est le comportement attendu si l'instance code> manager code> s'éteint et que vous avez toujours des pointeurs à la main et que vous y accédez?
@Kunalpuri Le gestionnaire sera vivant pendant la durée du processus, idéalement, lorsque le processus se ferme, les pointeurs intelligents se supprimeront comme la classe de gestionnaires détruite.
@Galik je ne suis pas tout à fait suivi. La classe Manager tiendra toujours la propriété des objets et le gestionnaire sera «vivant» jusqu'à ce que le processus soit sorti. Il n'y aurait donc pas de cas où la classe Manager supprimera les objets et renvoyera les pointeurs bruts.
@Jamesl je demande à votre opinion en cas d'indemnités brutes. Si vous aviez alloué de manière dynamique
manager code> instance et que vous avez fait
Supprimer code>. Après cela, allez-vous accéder à des pointeurs retournés par
tempfuncName code>?
Je voulais dire si vous obtenez des indications avant que le responsable ne soit détruit, n'utilisez pas ces pointeurs après la suppression du gestionnaire. Mais si le manager Toujours B> sera supprimé en dernier, alors vous allez bien, utilisez
std :: unique_ptr code> dans la classe Manager et retourner des pointeurs bruts.
@Kunalpuri non, la classe de gestionnaire existe pour maintenir les objets uniques_ptr afin que l'instance de gestionnaire soit supprimée, les pointeurs bruts qui ont été renvoyés par la fonction ne soient jamais accessibles (et que les pointeurs retournés ne soient pas mis en cache. La fonction agit comme Une fonction gettor et le code qui appelle cette fonction utiliseront les pointeurs bruts retournés et "oublier" à leur sujet après sa finition).
Cette question a d'excellentes réponses mais ce n'est pas un double précis.