IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

opérateur d'affectation: copie implicite ou explicite [Débat]


Sujet :

C++

  1. #81
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Si ce n'est qu'à ce moment là, ce n'est pas l'opérateur d'affectation "simple" qui sera utilisé, mais l'opérateur d'affectation par mouvement (celui qui prend, d'office, une rvalue référence : A(&& rhs) ).
    Franchement, tu exclus la move-semantic depuis le depuis de la conversasion, on est donc en C++03 et il n'y a pas d'opérateur d'affectation de mouvement.

    Citation Envoyé par koala01 Voir le message
    Je ne vois donc pas en quoi cela pourrait changer quoi que ce soit au niveau de la manière de déclarer l'argument de l'opérateur simple.
    J'ai fait un bench qui montre que ca change tout dans au moins un cas. Alors en effet ce cas ne se produira pas si tu implementes la version opérateur d'affectation par mouvement, mais dans ce cas le bench n'a pas de sens (tu n'as pas le choix de la forme de l'opérateur d'affection normal, c'est nécessairement const T& pour éviter les conflit avec T&&, cependant tu as exclus la move-semantic, donc ca ne rentre pas en compte).

    Citation Envoyé par koala01 Voir le message
    L'une des solutions qui pourraient être envisagée, c'est, bien sur, de faire appel à l'opérateur d'affectation par mouvement dans le corps de l'opérateur d'affectation simple, mais, pour que cela marche, il faut que l'argument que l'on transmettra soit un objet temporaire non nommé, sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    A & operator=(A /* const & */ rhs){
       *this.operator=(A(rhs)); 
        return this;
    }
    A ce moment là, tu auras peut etre une élision de la copie au niveau de l'opérateur par mouvement, mais comme tu devras, de toutes manières, faire une copie implicite, autant passer rhs par référence constante pour s'éviter d'avoir, en plus, une copie supplémentaire au moment de l'appel de l'opérateur d'affectation si on vient à passer rhs par valeur.
    Ce paragraphe n'a aucun sens, tu ne peux pas mettre const & en commentaire si tu as aussi la version T&& de l'opérateur d'affectation. Si tu n'as pas cette autre version mais que tu as un move-ctor, c'est en effet lui qui est appelé en cas de temporaire et éventuellement élidé.

    Citation Envoyé par koala01 Voir le message
    Bref, quoi qu'il en soit, l'argument de l'élision de copie ne représente pas un fondement technique sur lequel se baser pour décider s'il vaut mieux transmettre l'argument par valeur ou par référence constante à l'opérateur d'affectation normal
    Si ce n'est un bench qui montre 50% de perf en plus dans au moins un cas d'utilisation, en effet il n'y a aucun argument ...

  2. #82
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Citation Envoyé par koala01 Voir le message
    A la base, une rvalue est "simplement" quelque chose qui peut se trouver à droit de l'opérateur =.

    Donc : non toutes les rvalue ne sont pas des temporaires non nommés

    Les choses deviennent intéressantes lorsque l'on s'intéressent aux rvalue references

    Parce que, pour qu'il y ait rvalue reference, il faut qu'il y ait un objet temporaire.

    Mais objet temporaire ne veux pas forcément dire non nommé:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    std::string && foo(/* params */)
    {
        std::string temp;
        /* ... */ 
        return temp;
    }
    std::string && bar()
    {
        retrun "hello world";
    }
    La chaine (constante) "hello world" dans bar provoquera la création d'une std::string temporaire non nommée, ne pouvant donc être renvoyée que par valeur ou par rvalue reference.

    Mais, a priori, temp est aussi un temporaire (dans le contexte de la fonction) dans le sens où la std::string sera détruite lorsque l'on sortira de la portée dans laquelle elle a été déclarée.
    Norme 12.2.5
    The second context is when a reference is bound to a temporary. The temporary to which the reference is bound or the temporary that is the complete object of a subobject to which the reference is bound persists
    for the lifetime of the reference except:
    [...]
    — The lifetime of a temporary bound to the returned value in a function return statement (6.6.3) is not extended; the temporary is destroyed at the end of the full-expression in the return statement.
    Et si la norme dit "reference" sans préciser rvalue ou lvalue, c'est que ca s'applique aux deux. Ton code, comme cela a été dit avant, est donc bel et bien à ne pas faire.

  3. #83
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Mais si c'est le constructeur classique qui est appelé, il faut, déjà, récupérer la taille de manière explicite (est-ce taille() qu'il faut appeler, une autre fonction, accéder à un membre quelconque de la classe [EDIT] Et surtout: d'où vient elle [/EDIT]) et si tu arrives à faire en sorte que la taille soit indiquée de manière explicite, tu te retrouveras avec un array d'éléments, de la bonne taille, certes, mais dont les valeurs ne correspondent pas ([EDIT]ou du moins pas forcément[/EDIT]) aux valeurs de l'objet d'origine([EDIT]vu qu'elles correspondront aux valeurs éventuellement définies dans le constructeur[/EDIT]).
    Mais bien sur qu'il y a un constructeur d'appeler, le but de la copy elission est déviter d'en appeler deux lorsque ce n'est pas utile.

    Si tu prends
    Avec operator=(const a& rhs) tu as :
    • Un appel au constructeur A(int) pour construire ce temporaire
    • Le passage d'une ref const sur celui-ci
    • Suivi de la copie explicite via la constructeur


    Sans copy ellision et avec operator=(A rhs) tu as:
    • Un appel au constructeur A(int) (ou équivalent) pour construire un objet temporaire
    • Puis un appel au constructeur de copie pour copier ce temporaire dans rhs


    Avec copy ellision et operator=(A rhs) tu as
    • Un appel au constructeur A(int) qui construit directement rhs sans passer par un temporaire.


    Donc dans ce cas de figure, si le compilateur ne fait pas de copy ellision operator=(A rhs) coute la même chose que operator=(const A&) et permet de gagner un appel au constructeur de copie si le compilateur la fait.

    Et dans le cas où la copy ellision n'est tout simplement pas applicable (le paramètre n'est pas un temporaire), ça coute la même chose.

    Bref, comme déjà dit, operator=(A rhs), en C++03, permet dans quelques cas de gagner un appel au ctor de copie (ce qui peut être très couteux) et dans tous les autres cas ne coute pas plus cher.

  4. #84
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 629
    Points : 30 692
    Points
    30 692
    Par défaut
    Citation Envoyé par gl Voir le message
    Mais bien sur qu'il y a un constructeur d'appeler, le but de la copy elission est déviter d'en appeler deux lorsque ce n'est pas utile.

    Si tu prends
    Avec operator=(const a& rhs) tu as :
    • Un appel au constructeur A(int) pour construire ce temporaire
    • Le passage d'une ref const sur celui-ci
    • Suivi de la copie explicite via la constructeur


    Sans copy ellision et avec operator=(A rhs) tu as:
    • Un appel au constructeur A(int) (ou équivalent) pour construire un objet temporaire
    • Puis un appel au constructeur de copie pour copier ce temporaire dans rhs


    Avec copy ellision et operator=(A rhs) tu as
    • Un appel au constructeur A(int) qui construit directement rhs sans passer par un temporaire.


    Donc dans ce cas de figure, si le compilateur ne fait pas de copy ellision operator=(A rhs) coute la même chose que operator=(const A&) et permet de gagner un appel au constructeur de copie si le compilateur la fait.

    Et dans le cas où la copy ellision n'est tout simplement pas applicable (le paramètre n'est pas un temporaire), ça coute la même chose.

    Bref, comme déjà dit, operator=(A rhs), en C++03, permet dans quelques cas de gagner un appel au ctor de copie (ce qui peut être très couteux) et dans tous les autres cas ne coute pas plus cher.
    Quand tu veux assigner l'objet à un nouvel objet, je suis tout à fait d'accord avec le fait qu'il puisse y avoir élision de la copie, parce que l'élément qui se trouve à droite peut être considéré comme un objet temporaire (et encore, est-ce réellement l'opérateur d'affectation qui est appelé ).

    Mais je parle depuis le début du cas où tu veux assigner un élément existant par ailleurs à un autre élément existant (voire même à un objet nouvellement créé pour la cause).

    A ce moment là, tu ne peux pas éluder la copie, car c'est, purement et simplement, le seul moyen qui te permette de récupérer les données originale.

    Autrement dit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    int main()
    {
        A a(10);
        A b = A(15); // OK : potentielle élision de la copie, mais, a priori, ce n'est meme
                     // pas l'opérateur d'affectation qui sera appelé
       /* mais, avec le cas que je présente depuis le début */
       A c = a; // on ne peut EN AUCUN CAS éluder la copie !!! Le constructeur par copie
                // est le seul moyen de récupérer dans c des informations similaires à celles
                // sont issues de a
    }

  5. #85
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 582
    Points
    41 582
    Par défaut
    Mais a-t-on un jour dit le contraire?

  6. #86
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 629
    Points : 30 692
    Points
    30 692
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Mais a-t-on un jour dit le contraire?
    Toi, non, (et même Flob semble avoir fini par comprendre ce que j'esaye d'expliquer ) mais guillaume07 n'a décidément pas l'air de comprendre que la copie élision ne peut se faire que s'il ne faut pas, effectivement, commencer par copier un objet existant

  7. #87
    Débutant
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    688
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 688
    Points : 176
    Points
    176
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Toi, non, (et même Flob semble avoir fini par comprendre ce que j'esaye d'expliquer ) mais guillaume07 n'a décidément pas l'air de comprendre que la copie élision ne peut se faire que s'il ne faut pas, effectivement, commencer par copier un objet existant
    je suis assez confiant sur ma compréhension des concepts introduit dans ce post, je le suis moins concernant ta maîtrise des rvalue et même du principe de copy ellision au vue du nombres de posts et du nombres d'intervenants qu'il a fallut pour enfin? te mettre d'accord.

  8. #88
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 629
    Points : 30 692
    Points
    30 692
    Par défaut
    En fait, ces dernières pages mériteraient presque de se retrouver dans une discussion à part, mais, j'aimerais quand même en terminer avec cette histoire d'élision de la copie.

    Oui, j'ai bien compris (non flob, je n'ai pas ignoré ton bench ) que l'élision de la copie pouvait, quand elle s'applique, apporter un gain sans doute non négligeable en terme de performances.

    Cependant, nous sommes maintenant semble-t-il convenu (à part guillaume07) ne peut, en tout état de cause, intervenir que dans un "cas particulier"qui est que l'objet de droite doit être un objet temporaire, car, autrement, on ne pourra quoi qu'il advienne pas se passer de la copie.

    La bonne question est donc *peut etre* : Ce que j'appelle ici un "cas particulier" est il vraiment "une exception qui confirme la règle" ou est-ce plutôt ce qui se fera "en règle générale"

    A titre personnel, j'essaye de limiter au mieux la portée de mes variables et j'ai, de plus, pour habitude d'attendre d'avoir toutes les informations requises pour appeler le constructeur "qui convient le mieux" dans ma situation, ce qui fait qu'il est *relativement* rare que je doive faire une affectation sur une instance de structure (et d'autant plus rare de devoir le faire sur un objet temporaire).

    Les cas où la copie peut etre éludée sont donc relativement restreints dans mon cas, mais pour vous

  9. #89
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 629
    Points : 30 692
    Points
    30 692
    Par défaut
    Citation Envoyé par guillaume07 Voir le message
    je suis assez confiant sur ma compréhension des concepts introduit dans ce post, je le suis moins concernant ta maîtrise des rvalue et même du principe de copy ellision au vue du nombres de posts et du nombres d'intervenants qu'il a fallut pour enfin? te mettre d'accord.
    Je ne suis pas d'accord:

    Il a fini un grand nombre de posts et d'intervenants pour qu'on commence à parler de la même chose, ca, je te l'accorde.

    Cependant, j'ai sans arrêt présenté le même code sur lequel je me basais, et ce n'est qu'à partir du moment où l'on a pu se mettre d'accord sur le fait que je parlais d'assigner un élément existant que l'on a pu se mettre d'accord sur le reste (et que j'ai de mon coté admis le fait qu'il en allait autrement pour l'assignation d'un objet temporaire ou créé pour l'occasion).

    Tu sembles, à ce jour, le seul à ne pas accepter l'idée que la copie ne puisse en aucun cas être éludée lorsque l'on assigne un objet existant alors que si tu relis les interventions précédentes, j'ai fait clairement la distinction entre les deux situations possibles

  10. #90
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Je crois qu'on a tous compris depuis le début que l'élision ne peut avoir lieu que dans un cas. Par contre je crois que l'ensemble des intervenants a plus de mal à comprendre pourquoi tu veux exclue l'ensemble des cas où il peut y avoir élision, mais soit faison ca.

    Quant à quantifier cette proportion d'élision possible, je ne saurais le faire (je n'y ai pas réfléchi à vrai dire).

    Par contre la question que je me pose est : si les versions T et const T& sont identiques en performance sauf dans un cas (celui de l'élision que tu ne considères pas ici donc), pourquoi ne pas utiliser la version qui permet de booster les performances, même si ce boost n'a lieu que rarement ?

    Après si ta préférence à la forme const T& va de pair avec l'idéologie : "je prend par référence ce que je ne modifie pas". Je te rappel (ce que j'avais fait dans le premier post) que cette idéologie n'est pas partagée par tout le monde, et que je [c'est personnel] lui préfère "je laisse le compilateur faire les choses mieux que je ne saurais le faire", dans ce cas, j'ai besoin d'une copie ? Je mets un passage par valeur.

  11. #91
    Débutant
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    688
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 688
    Points : 176
    Points
    176
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Cependant, nous sommes maintenant semble-t-il convenu (à part guillaume07) ne peut, en tout état de cause, intervenir que dans un "cas particulier"qui est que l'objet de droite doit être un objet temporaire, car, autrement, on ne pourra quoi qu'il advienne pas se passer de la copie.
    :
    un objet temporaire tout à fait et non pas une rvalue.

  12. #92
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 629
    Points : 30 692
    Points
    30 692
    Par défaut
    Citation Envoyé par Flob90 Voir le message
    Je crois qu'on a tous compris depuis le début que l'élision ne peut avoir lieu que dans un cas. Par contre je crois que l'ensemble des intervenants a plus de mal à comprendre pourquoi tu veux exclue l'ensemble des cas où il peut y avoir élision, mais soit faison ca.

    Quant à quantifier cette proportion d'élision possible, je ne saurais le faire (je n'y ai pas réfléchi à vrai dire).
    A vrai dire, je n'y ai réellement réfléchi moi même qu'au moment de poser la question en analysant mes propres habitudes de codage
    Par contre la question que je me pose est : si les versions T et const T& sont identiques en performance sauf dans un cas (celui de l'élision que tu ne considères pas ici donc), pourquoi ne pas utiliser la version qui permet de booster les performances, même si ce boost n'a lieu que rarement ?
    Ca mérite qu'on y réfléchisse, mais, a priori, je serais assez d'avis de laisser faire le compilo
    Après si ta préférence à la forme const T& va de pair avec l'idéologie : "je prend par référence ce que je ne modifie pas". Je te rappel (ce que j'avais fait dans le premier post) que cette idéologie n'est pas partagée par tout le monde, et que je [c'est personnel] lui préfère "je laisse le compilateur faire les choses mieux que je ne saurais le faire", dans ce cas, j'ai besoin d'une copie ? Je mets un passage par valeur.
    En fait, je viens de me rendre compte que la "bonne" philosophie (si tant est qu'il y en ait une meilleure que les autres en tout cas) serait sans doute proche de "je transmet par référence ce dont je ne veux pas de copie, par référence constante si, en plus, je ne veux pas que ce soit modifié"

    Le problème que je vois à la mise en pratique de cette philosophie lorsque l'on parle à un débutant, c'est qu'il devient assez difficile d'expliquer en "quelques mots" (suffisamment génériques), comment arriver à déterminer s'il veut qu'une copie soit effectuée ou non

  13. #93
    Débutant
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    688
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 688
    Points : 176
    Points
    176
    Par défaut
    je sais que le thread portait principalement sur le c++ 98 mais voilà la règle exact en c++11 qui autorise ou non une copy elision( Paragraph 12.8/31)

    When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object, even if the constructor selected for the copy/move operation and/or the destructor for the object have side effects. [...] This elision of copy/move operations, called copy elision, is permitted in the following circumstances (which may be combined to eliminate multiple copies):

    — in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object (other than a function or catch-clause parameter) with the same cvunqualified type as the function return type, the copy/move operation can be omitted by constructing the automatic object directly into the function’s return value

    — in a throw-expression, when the operand is the name of a non-volatile automatic object (other than a function or catch-clause parameter) whose scope does not extend beyond the end of the innermost enclosing try-block (if there is one), the copy/move operation from the operand to the exception object (15.1) can be omitted by constructing the automatic object directly into the exception object

    when a temporary class object that has not been bound to a reference (12.2) would be copied/moved to a class object with the same cv-unqualified type, the copy/move operation can be omitted by constructing the temporary object directly into the target of the omitted copy/move

    — when the exception-declaration of an exception handler (Clause 15) declares an object of the same type (except for cv-qualification) as the exception object (15.1), the copy/move operation can be omitted by treating the exception-declaration as an alias for the exception object if the meaning of the program will be unchanged except for the execution of constructors and destructors for the object declared by the exception-declaration.

  14. #94
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    @guillaume07: Oui, et la règle est la même en C++03 le seul ajout sont les différents /move (et peut-etre quelques détails mineurs, j'ai pas fait le check, mais sur le principe les 4 situations d'élisions sont les même).

    @koala01: Oui, je suis d'accord que dans le cas général ce n'est pas nécessairement simple de l'expliquer à un débutant. Dans le cas de l'opérateur d'affectation (et d'autre cas à priori) tout repose sur la compréhension du besoin de cette copie : strong exception safety. Une fois que ceci est assimilé, il y a déjà pas mal de situation (les opérateurs d'affectation entre autre) où un débutant devrait comprendre qu'il doit y avoir copie et que donc le paramètre pourrait être passé par valeur.

    Après pour le cas spécifique de l'opérateur d'affectation, ce n'est pas inenvisageable de le présenter de manière idiomatique, et donc là le fait que ce soit T ou const T& ne change rien pour un débutant, ca revient à lui dire "pour un opérateur d'affectation, on a l'habitude de faire comme ca" sans nécessairement lui présenter les raisons, ce qui permet de lui conseiller la version T sans la détailler.

  15. #95
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Citation Envoyé par Flob90 Voir le message
    "je laisse le compilateur faire les choses mieux que je ne saurais le faire"
    Petite aparté surprenante la dessus.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    A a(0);
     
    // 1
    a = A(1);
     
    // 2
    a.~A();
    new (&a) A(1);
    (1) est systématiquement plus rapide (de peu, quelques pourcents, pas plus) que (2), dans le cas ou l'opérateur = prend une copie et non une référence constante.

    Faudrait que je regarde le code asm généré pour voir d'ou ça vient, mais faire confiance au compilo semble être une bonne idée.

  16. #96
    Débutant
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    688
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 688
    Points : 176
    Points
    176
    Par défaut
    Citation Envoyé par Iradrille Voir le message
    Petite aparté surprenante la dessus.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    A a(0);
     
    // 1
    a = A(1);
     
    // 2
    a.~A();
    new (&a) A(1);
    (1) est systématiquement plus rapide (de peu, quelques pourcents, pas plus) que (2), dans le cas ou l'opérateur = prend une copie et non une référence constante.

    Faudrait que je regarde le code asm généré pour voir d'ou ça vient, mais faire confiance au compilo semble être une bonne idée.
    si je ne dis pas de bêtises, dans 2) tu n'as pas a ré-alloué de la mémoire d'où le gain constaté (toute ou en partie)

  17. #97
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Citation Envoyé par guillaume07 Voir le message
    si je ne dis pas de bêtises, dans 2) tu n'as pas a ré-alloué de la mémoire d'où le gain constaté (toute ou en partie)
    Il me semble qu'il n'y a d'allocation de mémoire dans aucun des cas.
    En me basant sur le bench de Flob90, voila ce que j'obtiens :
    operator=(const ref) -> 9.38sec
    operator=(copie) -> 4.65sec
    placement new -> 4.73sec

    Niveau assembleur le code de l'opérateur= et du placement new sont très proche:
    Code X : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    	a = A();
    push        4 					; = sizeof(int), pour new
    call        edi					; contenu du ctor (eax = adresse du nouvel int) -> edi = @operator new(size_t size);
    mov         ecx,dword ptr [a] 	; ecx = adresse de a (a.i ici)
    push        ecx
    mov         dword ptr [a],eax 	; a.i = adresse du nouvel int alloué
    call        esi					; contenu du dtor -> esi = @free( p ); ( = free(a.i);)
    add         esp,8				; ??
    
    	a.~A();
    push        dword ptr [a]  
    call        esi					; contenu du dtor ( = free(a.i); )
    *mov        dword ptr [a],0		; a.i = nullptr
    	new (&a) A;
    push        4 					; = sizeof(int), pour new
    *mov        byte ptr [ebp-4],1	; ??
    call        edi					; contenu du ctor (= new, eax = adresse du nouvel int)
    add         esp,8				; ??  
    *mov        byte ptr [ebp-4],0	; ?? 
    mov         dword ptr [a],eax	; a.i = adresse du nouvel int alloué

    La classe A en question
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    struct A {
    	int* i;
    	A() : i(new int) {}
    	A(const A& a) : i(new int(*a.i)) {}
    	A& operator=(A a)
    	{ std::swap(i,a.i);  return *this; }
    	~A() { delete i; }
    	void foo(){}
    };
    Pour le placement new, il y a 3 instructions en plus (marqué d'une étoile, et l'ordre est différent).
    La différence vient de ces 3 instructions ?

    edit: marrant le couple new / free ^^

Discussions similaires

  1. Réponses: 7
    Dernier message: 17/08/2014, 15h20
  2. Constructeur de copie, et opérateur d'affectation.
    Par Invité dans le forum Débuter
    Réponses: 49
    Dernier message: 03/04/2010, 13h13
  3. Réponses: 12
    Dernier message: 12/07/2007, 14h17
  4. Classe Interface et Opérateur d'affectation!
    Par Rodrigue dans le forum C++
    Réponses: 6
    Dernier message: 07/02/2007, 14h45
  5. [langage] opérateur d'affectation binaires
    Par biglebowski13 dans le forum Langage
    Réponses: 6
    Dernier message: 21/11/2006, 09h51

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo