-1
votes

Pouvez-vous utiliser make_unique directement dans un appel de la fonction?

Je tente de mettre à jour du code qui distingue un nouvel objet. L'objectif est de le gérer avec un pointeur intelligent. Bouilli, il ressemble beaucoup à ceci:

class X
{
    shared_ptr<Y> yptr;

    X() : yptr(Y::create(  std::move(  std::make_unique<Z>(Z())  )  )){}
};

class Y
{
    unique_ptr<Z> zptr;
    static shared_ptr<Y> create(unique_ptr<Z> zp)
    {
        if(!zp) return nullptr;
        else return shared_ptr<Y>(new Y(std::move(zp)));
    }

    Y(unique_ptr<Z> zp) : zptr(std::move(zp)){}
}


4 commentaires

Quel est le problème avec l'utilisation de std :: make_shared () si vous voulez réellement un std :: partagé_ptr ?


Tout ce que std :: Déplacer fait l'objet à une prvalue. Si l'objet est déjà une pr devalue (par exemple, il n'a pas de nom ... c'est un temporaire), puis std :: Déplacer est superflu.


@ πνντα-ῥεῖ Le code impliqué est une méthode d'usine qui attribue ses membres sur la création. L'objet renvoyé par elle est destiné à être le seul propriétaire de l'article géré par le fichier unique_ptr. Un Shared_Ptr travaillerait dans ce cas mais il trahit l'intention.


@ François-Andrieux et c'est, je vais ajusterai ce qui précède. :)


3 Réponses :


0
votes

Réponse courte: oui

L'appel de la fonction std :: make_unique () retourne une rvalue, il n'est donc pas nécessaire de l'envelopper dans std :: Déplacer () Si vous la passe directement dans une autre fonction.


0 commentaires

0
votes

Ma question est, c'est le premier STD :: Déplacer () (autour de make_unique) nécessaire?

Si vous voulez dire cette ligne: xxx

alors non, il est complètement inutile que std :: make_unique retourne temporaire qui est déjà prvalue . Vous pouvez faire quelque chose comme ceci: xxx

au lieu de xxx

mais tout ce se déplace sont inutiles et le fait qu'il soit compilé montre clairement cela.


0 commentaires

0
votes

Oui! Le déplacement autour de make_unique est inutile.

std :: Déplacer pour convertir une référence de valeur L & (qui fait référence à un objet existant) dans une référence de valeur R. code> && (qui représente une valeur temporaire, ou quelque chose qui peut être déplacé de).

Si vous attribuez un unique_ptr à une variable nommée, vous devez en effet std :: Déplacer de celui-ci si vous souhaitez transférer sa propriété (généralement; voir ci-dessous ). Vous ne pouvez pas directement lier une référence de valeur R à une variable.

La valeur renvoyée par un appel d'expression ou de fonction, telle que le unique_ptr renvoyé par make_shared est temporaire, et il peut donc naturellement se lier à une valeur r expression et être déplacé-de l'implicitement.

Notez qu'il existe des cas particuliers où vous faites et que vous n'avez pas besoin d'utiliser std :: Déplacer :

  • Si vous avez une variable nommée dont le type est une référence de valeur R, vous do besoin de std :: Déplacer pour éviter de le transmettre par copie :

    myClass (std :: string && s): m_mystring (s) {} copier -Constructs m_mystring

    myClass (std :: string && s): m_mystring (std :: moue (s)) {} bouge-constructions m_mystring

    En général, les variables avec des noms ne sont pas implicitement déplacées.

  • Si vous retournez une variable locale par valeur à partir d'une fonction, cet objet peut être déplacé automatiquement, dans le soi-disant Optimisation de la valeur de retour nommée . Cela donne une belle vitesse à revenir à la valeur. Vous n'avez pas besoin de penser beaucoup à ce sujet dans la pratique, soyez juste conscient que retour std :: Déplacer (quoi que ce soit); est presque toujours faux.


3 commentaires

Excellente explication. J'ai un suivi, puisque vous avez soulevé une situation similaire. Si la fonction que le make_unique est adoptée doit transmettre à un constructeur avant qu'il ne soit réellement utilisé, est le STD :: Déplacer () maintenant nécessaire, ou est-ce seulement nécessaire à l'intérieur du constructeur lui-même (la destination finale)?


@ M.parker de Scott Meyers ' Essential Moderne C ++ "Un paramètre est toujours un lvalue, même si son type est une référence de rvalue. C'est-à-dire que, donné, étant donné VOID F (widget && W); , le paramètre w est un lvalue, même si son type est rvalue-référence-to- widget ".


Cela pourrait sembler être un point mineur, mais la question était "est le premier STD :: Move () nécessaire ", (pas "est le premier STD :: Déplacer () Un nécessaire). Donc, votre réponse est en fait "non!", pas "oui!". Je me suis déraillé pendant plusieurs minutes essayant de donner un sens à votre réponse, car j'ai vu votre "oui!" mais j'ai raté votre "ONU" mais et pensais que vous disiez le contraire de ce que vous dites réellement.