0
votes

Retourne un pointeur brut au lieu de une bonne pratique de codage?

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. XXX

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.

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.

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.

Toute aide et informations seraient grandement appréciées.


12 commentaires

Il y a des cas où seul un scalaire fera, pas une classe qui (très mal) émule un scalaire


Utilisez unique_ptr 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 car vos pointeurs ne sont pas uniques. Mais cela dépend de la Propriété et Lifetime 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 manager 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 instance et que vous avez fait Supprimer . Après cela, allez-vous accéder à des pointeurs retournés par tempfuncName ?


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 sera supprimé en dernier, alors vous allez bien, utilisez std :: unique_ptr 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.

3 Réponses :


0
votes

retourne un pointeur brut au lieu de une bonne pratique de codage unique?

non. Et oui. Il n'y a pas de réponse, car cela dépend du contexte. C'est assez simple cependant:

Transférer la propriété d'une ressource avec un pointeur brut est une mauvaise pratique de codage.

retourner un pointeur non propriétaire est une bonne pratique (bien que dans certains cas, une référence peut être meilleure).

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 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.


0 commentaires

0
votes

Passons à travers des options de ce que vous pouvez revenir

Si vous retournez unique_ptr s, alors par définition ces objets ne sont plus gérés par le gestionnaire. On dirait qu'ils devraient toujours être, alors unique_ptr n'est pas le bon type.

Si vous retournez Shared_ptr s, ou faibly_ptr 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 .

Si vous savez à coup sûr que ces objets existent, par exemple parce que le si filtré nulls, il serait vraiment agréable de retourner basoclass et s. Le problème est que vous ne pouvez pas avoir une référence en tant que valeur_type d'un conteneur. Dans ce cas, j'utiliserais std :: référence_wrapper comme contenu de votre conteneur, bien que basoclass * n'est pas beaucoup pire, comme référence_wrapper est fondamentalement un pointeur quand même.

Si un pointeur NULL est une option valide pour revenir, vous ne pouvez pas utiliser de références, donc basoclass * peut être votre meilleure option.


0 commentaires

1
votes

Utilisation de brut possédant strong> Pointeur est une mauvaise pratique.

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 std :: expérimental :: Observateur_ptr code> a été introduit pour exprimer clairement l'intention. (Mais c'est fondamentalement juste un pointeur). p>

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>

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;
};


1 commentaires

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).