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. #61
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    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 369
    Points : 41 519
    Points
    41 519
    Par défaut
    ^Tous les temporaires non-nommés sont des rvalue, mais toutes les rvalue sont-elles des temporaires non-nommés?

    @Koala01: Je vois qu'on est sur la même page.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par guillaume07 Voir le message
    si tu remontes le thread tu verras qu'il a été plusieurs fois précisé (dont au moins une fois par moi) que l'éllision de copie ne pourra avoir lieu uniquement si operator = est appelé avec une rvalue. Et c'est précisement pour optimiser ces cas là qu'il est préférable d'écrire l'opérateur d'assignement avec un paramètre par valeur et non pas comme une référence constante.
    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) ).

    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.

    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.

    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
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #63
    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
    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) ).
    Si tu n'as pas implémenté operator =(A&&) mais operator =(A), il faut que tu comprennes que même avec une rvalue
    c'est bien operator=(A) qui sera appelé
    .
    Si le compilateur supporte la copy ellision, la temporarie sera bindé directement dans le paramètre de l'operator =(A) autrement
    le constructeur par mouvement de A sera utilisé, ce qui tu en conviendras ne représente pas non plus une copie

    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
    C'est au contraire encore une fois l'unique raison pour laquelle il est préférable d'utiliser l'arguement par valeur

    la seule question qui reste à ce sujet est est-il préférable de fournir deux implémentations de operator = (pour les lvalue et pour les rvalue) où pour des raisons de simplifications se contenter de la forme operator =(A) (au prix d'un appel au constructeur de mouvement si appelé avec une rvalue)

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    ^Tous les temporaires non-nommés sont des rvalue, mais toutes les rvalue sont-elles des temporaires non-nommés?
    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.

    On ne pourrait donc pas renvoyer une référence dessus et la gérer, au niveau de la fonction appelante, sous une forme non constante (à moins de l'affecter à un objet bel et bien réel et non à une référence )

    @Koala01: Je vois qu'on est sur la même page.
    je crois en effet
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  5. #65
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    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 369
    Points : 41 519
    Points
    41 519
    Par défaut
    ^Euh, il me semble que ces deux fonctions sont fausses (retour par référence d'une variable locale).
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par guillaume07 Voir le message
    Si tu n'as pas implémenté operator =(A&&) mais operator =(A), il faut que tu comprennes que même avec une rvalue
    c'est bien operator=(A) qui sera appelé
    .
    Si le compilateur supporte la copy ellision, la temporarie sera bindé directement dans le paramètre de l'operator =(A) autrement
    le constructeur par mouvement de A sera utilisé, ce qui tu en conviendras ne représente pas non plus une copie
    Mais même un objet temporaire, fut il destiné à être détruit, doit être créé.

    Un objet temporaire n'apparait pas "comme ca, par magie"!!! Et encore moins s'il doit présenter un état similaire à un autre objet existant!!!

    C'est à dire qu'il y a d'office un constructeur qui est appelé !!!

    Et le seul constructeur qui soit en mesure de s'assurer que l'objet créé présente un état similaire à un autre objet de même type, c'est le constructeur par copie.

    Il sera donc appelé, que ce soit de manière implicite (dans le cas du passage par valeur) ou explicite (dans le cas du passage par référence constante), et cet appel au constructeur ne pourra pas être éludé.
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  7. #67
    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 Médinoc Voir le message
    ^Euh, il me semble que ces deux fonctions sont fausses (retour par référence d'une variable locale).
    oui ça provoque une dangling reference, ne faite surtout pas ça à la maison!

  8. #68
    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
    Mais même un objet temporaire, fut il destiné à être détruit, doit être créé.

    Un objet temporaire n'apparait pas "comme ca, par magie"!!! Et encore moins s'il doit présenter un état similaire à un autre objet existant!!!

    C'est à dire qu'il y a d'office un constructeur qui est appelé !!!

    Et le seul constructeur qui soit en mesure de s'assurer que l'objet créé présente un état similaire à un autre objet de même type, c'est le constructeur par copie.
    .

    en faite non le ctor classique est appelé (pour créer la temporaire) et c'est cette instance qui est fournit à l'operateur = dans le cas d'une copy ellision.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    ^Euh, il me semble que ces deux fonctions sont fausses (retour par référence d'une variable locale).
    Citation Envoyé par guillaume07 Voir le message
    oui ça provoque une dangling reference, ne faite surtout pas ça à la maison!
    Hé bien, justement non...

    C'est là tout l'attrait des rvalue reference

    Je vous propose un peu de lecture au sujet des rvalue references et de la sémantique de mouvement (dont Returning an explicit rvalue-reference from a function pour ce qui concerne le retour d'une rvalue reference )

    Le corps de la fonction est peut etre faux (j'aurais sans doute du appeler std::move), mais la signature de la fonction est correcte
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  10. #70
    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
    http://stackoverflow.com/questions/1...more-efficient

    "This returns a dangling reference, just like with the lvalue reference case. After the function returns, the temporary object will get destructed"

  11. #71
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    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 369
    Points : 41 519
    Points
    41 519
    Par défaut
    @koala01: Le seul exemple de retour de rvalue-reference dans le lien que tu m'as montré retourne une variable membre (ou globale) par référence, pas une variable locale.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  12. #72
    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 Médinoc Voir le message
    @koala01: Le seul exemple de retour de rvalue-reference dans le lien que tu m'as montré retourne une variable membre (ou globale) par référence, pas une variable locale.
    c'est exactment ça oui

  13. #73
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    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 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Somme-nous d'accord, aussi, qu'une variable peut être un temporaire non-nommé dans un contexte et nommé dans un autre? Dans une telle fonction par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    A make_A(int val)
    {
    	A temp(val); //Ici nommé
    	temp.doSomething();
    	return A; //Ici possible NRVO
    }
     
    int main(void)
    {
    	A a;
    	foo(make_A()); //Ici temporaire non-nommé passé à foo().
    }
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par guillaume07 Voir le message
    en faite non le ctor classique est appelé (pour créer la temporaire) et c'est cette instance qui est fournit à l'operateur = dans le cas d'une copy ellision.
    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]).

    Or, le but de l'opérateur d'affectation est, justement, en sorte de faire que les valeurs de l'objet courent correspondent à celles de l'objet assigné, en faisant en sorte que le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    int main()
    {
        A a(10);
        A b(15);
        a[3]=15;
        b[3] = 20;
        b= a;
        assert(b.size() == 10);
        assert(b[3]==15);
        assert(b[3]==a[3]);
    }
    ne provoque aucune erreur!

    Il t'est totalement impossible d'arriver à ce résultat si tu ne passe pas par le constructeur par copie!
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  15. #75
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    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 369
    Points : 41 519
    Points
    41 519
    Par défaut
    ^Normal, aucun des deux n'est une rvalue ni* un temporaire non-nommé.

    Je n'ai pas bien compris lequel est nécessaire, mais vu qu'on n'a aucun des deux c'est bon.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  16. #76
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    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 369
    Points : 41 519
    Points
    41 519
    Par défaut
    En extension de mon précédent exemple, voici un code qui montre bien l'élision de copie pour un retour de fonction chez moi:
    Code C++ : 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
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    #include <iostream>
    #include <algorithm>
    using namespace std;
     
    class A
    {
    	int *ptr;
    public:
    	void const *myAddr() const { return this; }
     
    	A(int val) : ptr(new int) { *ptr = val;           cout << myAddr() << ":ctor" << endl; }
    	A(A const &src) : ptr(new int) { *ptr = *src.ptr; cout << myAddr() << ":copy" << endl; }
    	~A() { delete ptr;                                cout << myAddr() << ":dtor" << endl; }
    	A& operator=(A tmp) { Swap(tmp);                  cout << myAddr() << ":opr=" << endl; return *this; }
    	void Swap(A& obj) { swap(ptr, obj.ptr); }
    };
     
    A make_A(int val)
    {
    	A a(val);
    	cout << "make_a: " << a.myAddr() << endl;
    	return a;
    }
     
    int main(void)
    {
    	A a(10);
    	cout << "here it comes!" << endl;
    	a = make_A(42);
    	return 0;
    }
    Code X : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    mingw32-g++.exe -O2 -Weffc++ -pedantic -std=c++98 -Wextra -Wall    -c "C:\Users\Frederic\Documents\VJ Codes CodeBlocks\CopyElision.cpp" -o "C:\Users\Frederic\Documents\VJ Codes CodeBlocks\CopyElision.o"
    mingw32-g++.exe  -o "C:\Users\Frederic\Documents\VJ Codes CodeBlocks\CopyElision.exe" "C:\Users\Frederic\Documents\VJ Codes CodeBlocks\CopyElision.o"   
    Process terminated with status 0 (0 minutes, 0 seconds)
    0 errors, 0 warnings
     
    Checking for existence: C:\Users\Frederic\Documents\VJ Codes CodeBlocks\CopyElision.exe
    Executing: C:\Program Files\CodeBlocks/cb_console_runner.exe "C:\Users\Frederic\Documents\VJ Codes CodeBlocks\CopyElision.exe" (in C:\Users\Frederic\Documents\VJ Codes CodeBlocks)
    Code X : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    0x22ff0c:ctor
    here it comes!
    0x22ff08:ctor
    make_a: 0x22ff08
    0x22ff0c:opr=
    0x22ff08:dtor
    0x22ff0c:dtor
    
    Process returned 0 (0x0)   execution time : 0.152 s
    Press any key to continue.
    (au passage, je suis choqué que l'affichage par défaut d'un void* ne force pas de taille minimale)
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    En extension de mon précédent exemple, voici un code qui montre bien l'élision de copie pour un retour de fonction chez moi:
    Code C++ : 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
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    #include <iostream>
    #include <algorithm>
    using namespace std;
     
    class A
    {
    	int *ptr;
    public:
    	void const *myAddr() const { return this; }
     
    	A(int val) : ptr(new int) { *ptr = val;           cout << myAddr() << ":ctor" << endl; }
    	A(A const &src) : ptr(new int) { *ptr = *src.ptr; cout << myAddr() << ":copy" << endl; }
    	~A() { delete ptr;                                cout << myAddr() << ":dtor" << endl; }
    	A& operator=(A tmp) { Swap(tmp);                  cout << myAddr() << ":opr=" << endl; return *this; }
    	void Swap(A& obj) { swap(ptr, obj.ptr); }
    };
     
    A make_A(int val)
    {
    	A a(val);
    	cout << "make_a: " << a.myAddr() << endl;
    	return a;
    }
     
    int main(void)
    {
    	A a(10);
    	cout << "here it comes!" << endl;
    	a = make_A(42);
    	return 0;
    }
    Code X : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    mingw32-g++.exe -O2 -Weffc++ -pedantic -std=c++98 -Wextra -Wall    -c "C:\Users\Frederic\Documents\VJ Codes CodeBlocks\CopyElision.cpp" -o "C:\Users\Frederic\Documents\VJ Codes CodeBlocks\CopyElision.o"
    mingw32-g++.exe  -o "C:\Users\Frederic\Documents\VJ Codes CodeBlocks\CopyElision.exe" "C:\Users\Frederic\Documents\VJ Codes CodeBlocks\CopyElision.o"   
    Process terminated with status 0 (0 minutes, 0 seconds)
    0 errors, 0 warnings
     
    Checking for existence: C:\Users\Frederic\Documents\VJ Codes CodeBlocks\CopyElision.exe
    Executing: C:\Program Files\CodeBlocks/cb_console_runner.exe "C:\Users\Frederic\Documents\VJ Codes CodeBlocks\CopyElision.exe" (in C:\Users\Frederic\Documents\VJ Codes CodeBlocks)
    Code X : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    0x22ff0c:ctor
    here it comes!
    0x22ff08:ctor
    make_a: 0x22ff08
    0x22ff0c:opr=
    0x22ff08:dtor
    0x22ff0c:dtor
    
    Process returned 0 (0x0)   execution time : 0.152 s
    Press any key to continue.
    (au passage, je suis choqué que l'affichage par défaut d'un void* ne force pas de taille minimale)
    Cet exemple ne prouve malheureusement qu'une seule chose: le respect strict d'une règle aussi vieille que C++ : la durée de vie d'un objet renvoyé par valeur s'étend à celle de l'objet qui le récupère.

    C'est effectivement une certaine forme d'élision de la copie, mais pas celle qui nous intéresse ici
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  18. #78
    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
    moi je jette l'éponge , en espérant que quelqu'un de plus pédagogique parvienne à te mettre d'accord.

  19. #79
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    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 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Euh, je ne vois pas quelle autre élision de copie existe.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  20. #80
    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 Médinoc Voir le message
    ^Tous les temporaires non-nommés sont des rvalue, mais toutes les rvalue sont-elles des temporaires non-nommés?

    Même si l'expresion std::move(a) est une rvalue, son évaluation ne créer pas d'objet temporaire, le c++11 à donc apporté une nouvelle notion: les xvalue.

    on peut retenir le schéma ci-dessous :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
            expressions
              /     \
             /       \
            /         \
        glvalues   rvalues
          /  \       /  \
         /    \     /    \
        /      \   /      \
    lvalues   xvalues   prvalues

    Donc "mais toutes les rvalue sont-elles des temporaires non-nommés?", non seulement les prvalues (“pure” rvalue)

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