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 :

constructeur par copie


Sujet :

C++

  1. #1
    Membre expérimenté
    Inscrit en
    Septembre 2006
    Messages
    414
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 414
    Par défaut constructeur par copie
    bonjour a tous,

    voila je suis confronté a un drole de probleme, mon code est compilable sous vc++ mais pas avec g++...

    voila le code:

    Code : 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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    #include<iostream>
    #include<fstream>
    using namespace std;
     
     
     
     
     
     
     
     
     
     
     
    class CFract{
     
     
     
    public:
     
    	int a,b;
     
    	void Affiche(){
     
     
     
    		//printf("CFract @=%08lX (%d,%d)\n",this,a,b); //l=long , X=hexa
    		cout << "CFract @=" << "(" << a << "," << b << ")" << endl;
     
     
     
    	}
     
     
     
    	//Constructeur par copie
     
    	CFract(CFract & f){		
     
     
     
    		a=f.a;
     
    		b=f.b;
     
    		cout << "Ctor copie: ";Affiche();
     
     
     
    	}
     
     
     
    	//Constructeur 0 a 2 arguments
     
    	CFract(int _a=1,int _b=1) : a(_a),b(_b)	{
     
     
     
    		cout << "Ctor 0-2 param: "; Affiche();
     
     
     
    	}
     
     
     
    	//Surcharge "+"
     
    	CFract operator+(const CFract & f) const /* pour que this ne soit pas modifié */{
     
     
    		CFract res;
     
    		res.a = f.a *b + a*f.b;
     
    		res.b = f.b * b;
     
     
     
    		return res; 
     
     
    	}
     
     
     
    	//Destructeur
     
    	~CFract(){
     
     
     
    		cout << "Dtor:";Affiche();
     
     
     
    	}
     
     
     
    	//ecriture sur fichier
     
    	void Affiche(ofstream & pf) const {
     
     
     
    		//fprintf(pf,"CFract @=%08lX (%d,%d)\n",this,a,b); //l=long , X=hexa
    		pf << "CFract @=" << this << " (" << a << "," << b << ")" << endl;
     
     
     
     
    	}
     
    	//redirection de flux
     
    	ofstream & operator>>(ofstream & pf)const{
     
     
     
    		Affiche(pf);
     
     
     
    		return pf;
     
     
     
    	}
     
     
     
     
     
     
     
    };
     
     
     
     
     
    ofstream & operator<<(ofstream & pf, const CFract& f){
     
     
     
    	f.Affiche(pf);
     
    	return pf;
     
     
     
    }
     
     
     
     
     
    void Test1()
     
    {
     
    	//CFract f1={21,3};
     
     
     
     
     
    	CFract f1;
     
    	f1.a=21;
     
    	f1.b=3;
     
    	CFract f2(f1);
     
    	CFract f3('z');
     
    	f1.Affiche();
     
    	f2.Affiche();
     
    	f3.Affiche();
     
     
     
    	//CFract f4(2.4);
     
    	//f4.Affiche();
     
     
     
    	CFract f5;
     
    	f5=f1+f3;
     
    	f5.Affiche();
     
    	//FILE * pf=fopen("show.txt","wt");
    	ofstream pf("show.txt");
     
     
     
     
     
    	f5.Affiche(pf);
     
    	f1>>(f2>>pf);
     
    	pf<<f1<<f2;
     
     
     
    	pf.close();
     
     
     
    }
     
     
     
     
     
     
     
    int main(){
     
     
     
     
     
    	Test1();
    	return 0;
     
     
    }
    l'erreure signalée est :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    fract.cpp: In function «void Test1()»:
    fract.cpp:102: erreur: no matching function for call to «CFract::CFract(CFract)»
    fract.cpp:30: note: candidats sont: CFract::CFract(int, int)
    fract.cpp:21: note:                 CFract::CFract(CFract&)
    ligne 102: f5=f1+f3;

    ce qui correspond a l'utilisation de la surcharge de l'operateur "+"
    suivi d'une construction par copie...
    sous vc++ la construction se fait correctement
    avec g++ probleme, il veut un constructeur avec en argument la classe elle meme et pas la reference...

    mon prof m'a donné comme réponse:
    "gcc etant libre, il doit etre rempli de bugs" ....


    merci d'avance

    kamou

  2. #2
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut
    Citation Envoyé par kamouminator Voir le message
    mon prof m'a donné comme réponse:
    "gcc etant libre, il doit etre rempli de bugs" ....
    Ouais, tu ne lui dira pas je suppose mais ca, c'est ce qu'on dit quand on sait pas quoi dire.

    Je pense plutôt que le problème est dans ton constructeur de copie.

    La forme normale est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    	//Constructeur par copie
    	CFract(const CFract & f){
    ...
    Donc en l'occurence, c'est putôt gcc qui a raison mais c'est normal, c'est un logiciel libre (donc tout le monde peu regarder les sources, les corriger et en faire profiter la communauté)
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  3. #3
    Membre expérimenté
    Inscrit en
    Septembre 2006
    Messages
    414
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 414
    Par défaut
    ok merci ! ca marche !!

    je le lui dirai peut etre a la fin de l'année ^^

  4. #4
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 477
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 477
    Par défaut
    Citation Envoyé par ram-0000 Voir le message
    Donc en l'occurence, c'est putôt gcc qui a raison mais c'est normal, c'est un logiciel libre (donc tout le monde peu regarder les sources, les corriger et en faire profiter la communauté)
    D'autant que dans le logiciel propriétaire, reconnaître un bug auprès de ses clients peut avoir des conséquences économiques désastreuses.

  5. #5
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Désolé de vous contredire, mais :
    Est une définition légale pour un constructeur par recopie. Elle est moins utile que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    CFract(CFract const & f)
    mais peut quand même servir.

    Citation Envoyé par Le standard 12.8/2
    A non-template constructor for class X is a copy constructor if its first parameter is of type X&, const X&, volatile X& or const volatile X&, and either there are no other parameters or else all other parameters have default arguments
    D'ailleurs, je ne vois pas où le constructeur par copie est supposé être appelé dans son code. Je verrai bien une erreur s'il avait écrit (comme on écrirait probablement dans du vrai code) :
    Dans ce cas, il y aurait bien tentative d'appel du constructeur de recopie avec un temporaire, ce qui n'est pas possible avec un argument qui est une référence non const.

    Honnêtement, dans ce cas, même si le code initial n'est pas très bon, je pense qu'il devrait compiler, et que c'est gcc qui se trompe ici.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  6. #6
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Ça marche avec Microsoft Visual C++ parce qu'il n'est pas conforme à la norme.
    Il permet la référence non-constante de temporaires. Ce qui n'est tout simplement pas autorisé.
    Il n'est possible de référencer des temporaires qu'avec des références const.

  7. #7
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Peux-tu me dire dans le code en question où une référence non constante vers un temporaire est utilisée ?

    Je rappelle la situation :
    - Le code déclenchant l'erreur est f5=f1+f3;
    - L'opérateur = n'est pas spécifié.
    - Seul est spécifié le constructeur par recopie, qui prend une référence non constante en paramètre.
    - Quand on modifie ce constructeur pour qu'il prenne en paramètre un référence constante, le code se met à marcher
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  8. #8
    Membre expérimenté
    Inscrit en
    Décembre 2003
    Messages
    272
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 272
    Par défaut
    C'est d'autant plus suspect que le constructeur en question n'est pas appelé :
    Code : 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
    #include<iostream>
     
    class CFract {
    public:
        int a;
        void Affiche(void) const { std::cout << "[" << this << "]=(" << a << ")" << std::endl; }
        CFract(CFract &f) { a = f.a; std::cout << "Ctor copie: "; Affiche(); }
        CFract(const CFract &f) { a = f.a; std::cout << "Ctor copie const: "; Affiche(); }
        CFract &operator=(const CFract &f) { if (this == &f) { return *this; } a = f.a; std::cout << "operator=: "; Affiche(); }
        CFract(int aa = 1) : a(aa) { std::cout << "Ctor : "; Affiche(); }
        CFract operator+(const CFract &f) const { CFract res; res.a = f.a + a; return res; }
        ~CFract() { std::cout << "Dtor:"; Affiche(); }
    };
     
    int main() {
        CFract f1(21);
        CFract f2(2);
        CFract f3;
        f3 = f1 + f2;
        return 0;
    }
    donne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Ctor : [0x22ff30]=(21)
    Ctor : [0x22ff20]=(2)
    Ctor : [0x22ff10]=(1)
    Ctor : [0x22ff00]=(1)
    operator=: [0x22ff10]=(23)
    Dtor:[0x22ff00]=(23)
    Dtor:[0x22ff10]=(23)
    Dtor:[0x22ff20]=(2)
    Dtor:[0x22ff30]=(21)

  9. #9
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    En effet, je ne vois aucun endroit où le constructeur par copie est appelé sur un temporaire non-nommé...
    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.

  10. #10
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Le message d'erreur dit bien qu'il tente d'appeler le constructeur de CFract avec un temporaire de type CFract, et qu'aucun constructeur ne matche.
    Après, comment cet appel est invoqué dans son code, je ne sais pas. Peut-être dans le retour par valeur de operator+ ?

  11. #11
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Citation Envoyé par loufoque Voir le message
    Le message d'erreur dit bien qu'il tente d'appeler le constructeur de CFract avec un temporaire de type CFract, et qu'aucun constructeur ne matche.
    Jusque là, on est d'accord...
    Citation Envoyé par loufoque Voir le message
    Après, comment cet appel est invoqué dans son code, je ne sais pas. Peut-être dans le retour par valeur de operator+ ?
    J'avoue que je ne sais pas trop quel est le comportement du retour par valeur de l'opérateur+. Après tout, dans cet opérateur, res n'est pas un temporaire.

    Mais je m'étais posé la question, et j'avais modifié son code pour supprimer l'addition. Résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    f5=f1+f3;
    f5= CFrac(1); //1
    Ne marchent pas, alors que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    f5 = f3;
    f5 = 1; // 2
    Marchent.

    Le fait que les lignes 1 et 2 aient un comportement différent me semble vraiment étrange. J'ai quand même l'impression que gcc a un problème ici, même si probablement visual C++ n'a le comportement correct que grâce à sa trop grande permissivité vis à vis des références non constantes et des temporaires.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  12. #12
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Pour plus de sûreté, j'ai réduit le code au minimal, et tenté de voir ce que ça donne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    struct A
    {
    	A (A &a) {}
    	A() {};
    };
     
    int main()
    {
    	A a1;
    	a1 = A();
    }
    Avec gcc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    min.cpp:10: error: no matching function for call to `A::A(A)'
    min.cpp:3: note: candidates are: A::A(A&)
    Avec Comeau online :
    Succès

    J'ai bien envie de saisir un bug report à gcc, mais je ne sais pas trop où c'est, ni comment vérifier qu'il n'existe pas déjà (j'utilise très peu gcc). Est-ce que quelqu'un pourrait le prendre en charge ?
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  13. #13
    Membre expérimenté
    Profil pro
    Étudiant
    Inscrit en
    Avril 2007
    Messages
    181
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2007
    Messages : 181
    Par défaut
    On m'a enseigné que le prototype d'un constructeur par copie était obligatoirement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ClassName(const ClassName& a);
    L'erreur de compilation provoquée g++ m'apparaît donc tout à fait légitime.
    (Que dit la norme ?)

  14. #14
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Citation Envoyé par JolyLoic Voir le message
    J'avoue que je ne sais pas trop quel est le comportement du retour par valeur de l'opérateur+. Après tout, dans cet opérateur, res n'est pas un temporaire.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    CFract operator+(const CFract & f) const 
    {
         CFract res;
         res.a = f.a *b + a*f.b;
         res.b = f.b * b;
         return res; 
    }
    return res n'est pas sensé faire une copy a partir du constructeur de recopie??

  15. #15
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Citation Envoyé par Haze. Voir le message
    On m'a enseigné que le prototype d'un constructeur par copie était obligatoirement :
    On t'as mal enseigné alors...
    Citation Envoyé par Haze. Voir le message
    (Que dit la norme ?)
    Je l'ai citée quelques posts plus haut.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  16. #16
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    @JolyLoic: Cela me parait en effet être un bug: Je ne pense pas que la norme autorise ainsi à remplacer ctor défaut + opérateur= par ctor copie, alors qu'il s'agit de deux instructions différentes...
    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. #17
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Citation Envoyé par Mongaulois Voir le message
    return res n'est pas sensé faire une copy a partir du constructeur de recopie??
    Si, mais la question est est-ce que le constructeur de copie est appelé sur un temporaire (ce que le constructeur du posteur initial ne peut pas faire, probablement une erreur dans son code, mais on parle depuis quelques posts du comportement d'un compilateur, pas de comment écrire le bon code) ou sur un non temporaire (ce qu'il peut faire).

    Et de toute façon, il y a un problème même sans l'opérateur+...
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  18. #18
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Sinon, ça pourrait simplement être que le operator= par défaut prend une référence const.
    Il me semble que convertir une rvalue vers une référence const peut générer une copie, même si en pratique aucun compilateur ne le fait.

    D'ailleurs, GCC génère bien une erreur quand on tente de passer un temporaire d'un type non copiable à une fonction prenant une référence constante.
    (GCC 4.3 ne le fait pas, par contre ; ça doit être les références de C++0x qui ont envahi C++03 -- c'est un bug, même si c'est pas bien grave)
    Ça semble effectivement être ça, puisque le code du premier post compile avec GCC 4.3.

  19. #19
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Hum, effectivement, je découvre un truc ici... Bien vu...

    Citation Envoyé par Version 98 (8.5.3/5)
    If the initializer expression is an rvalue, with T2 a class type, and “cv1 T1” is referencecompatible with “cv2 T2,” the reference is bound in one of the following ways (the choice is implementationdefined):
    — The reference is bound to the object represented by the rvalue (see 3.10) or to a subobject within that object.
    — A temporary of type “cv1 T2” [sic] is created, and a constructor is called to copy the entire rvalue object into the temporary. The reference is bound to the temporary or to a subobject within the temporary.93)
    The constructor that would be used to make the copy shall be callable whether or not the copy is actually done.

    Citation Envoyé par Version 0x (8.5.3/5)
    If the initializer expression is an rvalue, with T2 a class type, and “cv1 T1” is reference-compatible with “cv2 T2,” the reference is bound to the object represented by the rvalue (see 3.10) or to a sub-object within that object.
    Et effectivement, quand je désactive les extensions C++0X de Comeau, mon code de test précédent produit une erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    "ComeauTest.c", line 10: error: "A::A(A &)", required for copy that was eliminated,
              is not callable because reference parameter cannot be bound to rvalue
      	a1 = A();
      	     ^
    Et bien, je peux dire que je suis content que ce truc ait été enlevé dans C++0x, car ça m'a l'air tout sauf naturel... Et en tout cas, il n'y avait pas de bug dans gcc.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  20. #20
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Citation Envoyé par JolyLoic Voir le message
    Et en tout cas, il n'y avait pas de bug dans gcc.
    En effet, il était dans la norme.

    Et je vois que Comeau est vachement plus explicite pour ces messages d'erreurs. Ce compilo commence à m'intéresser...
    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.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. [POO] Constructeur par copie
    Par kacedda dans le forum C++
    Réponses: 16
    Dernier message: 05/05/2007, 12h38
  2. [Debutant] Problème avec un constructeur par copie
    Par Drannor dans le forum Débuter
    Réponses: 5
    Dernier message: 12/03/2007, 09h15
  3. Réponses: 5
    Dernier message: 03/12/2006, 15h55
  4. Constructeur par copie et std::list
    Par Captain_JS dans le forum SL & STL
    Réponses: 5
    Dernier message: 13/12/2005, 19h15
  5. [deb.]Constructeur par copie
    Par Marc_3 dans le forum Débuter
    Réponses: 4
    Dernier message: 19/11/2005, 13h33

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