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 :

Surcharge de l'opérateur +=


Sujet :

C++

  1. #1
    Membre à l'essai Avatar de neodole
    Homme Profil pro
    Ingénieur après-vente
    Inscrit en
    Avril 2012
    Messages
    32
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur après-vente
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2012
    Messages : 32
    Points : 21
    Points
    21
    Par défaut Surcharge de l'opérateur +=
    Bonjour,

    J'ai créé une classe Polynome dans laquelle j'ai surchargé les opérateurs + et * pour me permettre d'additionner et multiplier 2 polynômes entre eux. J'essaye également du surchargé l'opérateur += et *+ mais je rencontre des problèmes.

    Polynome.cpp:

    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
     
    polynome operator+= (polynome P, polynome Q)
    {	
    	float * coeff;
    	int degre = max(P.degre,Q.degre);
    	coeff=new float [degre+1];
    	for (int i=0;i<degre+1;i++)
    	{
    		if (i<= min(P.degre,Q.degre))
    		{
    			coeff[i]=P.coeff[i]+Q.coeff[i];
    			//std::cout << coeff[i] << std::endl;
    		}
    		else
    		{
    			if (P.degre<Q.degre)
    			{			
    				coeff[i]=Q.coeff[i];
    			}
    			else
    			{
    				coeff[i]=P.coeff[i];
    			}
    		}
    	}
    	polynome Result(degre,coeff); // fait appel à un constructeur créant un polynome à partir des paramètres Int et *Flaot
    	delete[] coeff;
    	return Result;
    }
    Polynome.h:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    friend polynome operator+=(polynome,polynome);
    main.cpp:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    	cout << "(P+=Q)(2.1)= " << (P+=Q).Eval(2.1) << "\n" << endl; // partie 1
     
    	P+=Q;                                                                                       // partie 2
    	cout << P.Eval(2.1) << endl;
    Ce que je ne comprends pas c'est pourquoi j'obtiens le bon résultat avec la partie 1 du main.cpp et pas avec la partie 2. Le P.Eval qui est une méthode de classe pour évaluer le polynome en une valeur ne me donne pas la même valeur que celle de la partie 1...

    Quelques peut-il m'aider?

    Je débute en POO et la gymnastique mentale est loin d'être simple.

    Merci d'avance

    Neodole

  2. #2
    Nouveau membre du Club
    Inscrit en
    Juin 2013
    Messages
    18
    Détails du profil
    Informations forums :
    Inscription : Juin 2013
    Messages : 18
    Points : 35
    Points
    35
    Par défaut
    salut

    le but de l'opérateur += est double :
    - modifier une variable
    - renvoyer le resultat de l'opération

    la façon dont tu as programmé ton opérateur += fait que P+=Q
    - renvoie la valeur de l'addition
    - NE modifie PAS la variable P

    pour corriger cela tu peux remplacer
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    P.degre = max(P.degre,Q.degre);
    delete[] P.coeff;
    P.coeff=coeff;
    une autre façon plus conventionnelle consisterait à déclarer += à l'intérieur de la class polynome en rentrant seulement le second opérande comme paramètre

    @+

  3. #3
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 071
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 071
    Points : 12 116
    Points
    12 116
    Par défaut
    Votre implémentation n'est pas canonique.
    Lisez la documentation du C++ pour avoir des exemples d'implémentations canonique des opérateurs +, +=, =, ....

    Dans le première partie du code, vous appelez "Eval" sur l'objet retourné par la méthode "+=".
    Qui est le résultat de "P+=Q".

    Votre opérateur "+=" ne modifie ni P ni Q, c'est l'une des erreurs de votre implémentation, cf. la documentation C++.

    Donc ligne 4, vous appelez la méthode "+=" qui calcule peut-être "P+Q" mais ne modifie ni P ni Q et le résultat du calcul est sauvegardé nullpart.

    Donc "P.Eval(2.1)" appel "Eval" sur l'objet P, qui n'a jamais changé depuis le début du programme.

    Avec votre méthode "+=" bancale, vous devez écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    polynome Resultat= (P+=Q);                                                                                       // partie 2
    	cout << Resultat.Eval(2.1) << endl;

  4. #4
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 470
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 470
    Points : 6 106
    Points
    6 106
    Par défaut
    Bonjour,

    Il semble que ton membre polynome::coeff soit de type float*.
    A la place, je conseille que polynome::coeff soit de type std::deque<float>, std::deque<double>, std::vector<float> ou std::vector<double>.

    Alors, voici comment j'aurais implémenté += et + :
    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
    polynome& polynome::operator+=(const polynome& other) // Note que je fais un passage par référence constante.
    {
        const size_t myCoeffCount    = coeff.size();
        const size_t otherCoeffCount = other.coeff.size();
     
        if(myCoeffCount < otherCoeffCount)
            coeff.resize(otherCoeffCount, 0.0);
     
        for(size_t k = 0; k < otherCoeffCount; ++k)
            coeff[k] += other.coeff[k];
     
        return *this;
    }
     
    polynome operator+(polynome P, const polynome& Q)
    {
        return P += Q;
    }

  5. #5
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    739
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 739
    Points : 3 627
    Points
    3 627
    Par défaut
    Plop,

    Un truc concernant les perfs et les opérateurs qui créent de nouveau objet (comme l'opérateur +): toujours séparer la modification (P += Q) du retour (return P) sinon le compilateur fera une double copie.
    La première fois pour le paramètre P, la seconde pour le retour de fonction, car P+=Q retourne une référence qui empêche la RVO/move-ctor de s'appliquer.

  6. #6
    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 518
    Points
    41 518
    Par défaut
    Généralement, entre les opérateurs + et +=, l'un est généralement implémenté via un appel à l'autre. Le sens de cet appel dépend de la simplicité ou non d'une telle création (allocation mémoire, etc.):

    • Une classe simple, pour laquelle l'addition consiste juste à additionner des valeurs membres, peut implémenter un opérateur += simple et l'appeler depuis un opérateur +:
      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
      class Vector3D
      {
      	int x, y, z;
      public:
      	Vector3D & operator+=(Vector3D const & right)
      	{
      		x += right.x;
      		y += right.y;
      		z += right.z;
      		return *this;
      	}
      };
       
      Vector3D operator+(Vector3D const & left, Vector3D const & right) 
      {
      	Vector3D ret = left;
      	ret += right;
      	return ret;
      }
    • Par contre, une classe plus compliquée (par exemple, une classe comme std::string qui considère les opérateurs + et += comme de la concaténation) devant faire de l'allocation mémoire, implémentera généralement le +, avant de faire le += en suivant l'idiome copy-and-swap:
      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
      32
      33
      34
      35
      36
      37
      38
      39
      class Chaine
      {
      	unique_ptr<char[]> buffer_;
       
      	explicit Chaine(unique_ptr<char[]> && buffer) : buffer_(move(buffer)) {}
      public:
      	Chaine(const char *chaineC) : buffer_(make_unique<char[]>((chaineC!=NULL ? strlen(chaineC) : 0)+1) { if(chaineC!=NULL) strcpy(buffer_, chaineC); else buffer_[0]='\0'; }
       
      	//Constructeurs et opérateurs = canoniques avec copy-and-swap
      	Chaine() :buffer_(make_unique<char[]>(0)) {}
      	Chaine(Chaine const& right) : Chaine(right.c_str()) {}
      	Chaine(Chaine && right) : buffer_(move(right.buffer_)) { right.buffer_ = nullptr; }
      	void swap(Chaine & right) { buffer_.swap(right.buffer_); }
      	Chaine& operator=(Chaine tmp) { swap(tmp); return *this; }
      	Chaine& operator=(Chaine&& right) { Chaine tmp(move(right)); swap(tmp); return *this; }
       
      	size_t length() const { return strlen(buffer_); }
      	char const * c_str() const { return buffer_; }
       
      	//Fonction de concaténation ayant accès au constructeur privé
      	static Chaine Concat(Chaine const& left, Chaine const& right)
      	{
      		size_t cchLength = left.length() + right.length();
      		unique_ptr<char[]> buffer2 = make_unique<char[]>(cchLength+1);
      		strcpy(buffer2, left.c_str());
      		strcat(buffer2, right.c_str());
      		return Chaine(move(buffer2));
      	}
      };
       
      Chaine operator+(Chaine const& left, Chaine const& right)
      {
      	return Chaine::Concat(left, right);
      }
      Chaine& operator+=(Chaine& left, Chaine const& right)
      {
      	Chaine tmp = left+right;
      	left.swap(tmp); return left;
      }

    Edit: Corrigé constructeur pour le cas où chaineC est un pointeur nul.
    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.

  7. #7
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 470
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 470
    Points : 6 106
    Points
    6 106
    Par défaut
    Citation Envoyé par jo_link_noir Voir le message
    Un truc concernant les perfs et les opérateurs qui créent de nouveau objet (comme l'opérateur +): toujours séparer la modification (P += Q) du retour (return P) sinon le compilateur fera une double copie.
    La première fois pour le paramètre P, la seconde pour le retour de fonction, car P+=Q retourne une référence qui empêche la RVO/move-ctor de s'appliquer.
    Je viens de faire le test avec Visual C++ 2010 Express et je n'observe pas de différence.
    Quand je passe en premier paramètre une lvalue, j'ai une double copie : une pour le premier paramètre et une pour le retour.
    Quand je passe en premier paramètre une rvalue, j'ai une simple copie : une pour le retour.

    Extrait de Integer.cpp :
    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
    Integer::Integer(const Integer& other) :
    	m_data(other.m_data)
    {
    	std::cout << "Copie de Integer (constructeur).\n";
    }
     
    Integer& Integer::operator=(const Integer& other)
    {
    	m_data = other.m_data;
    	std::cout << "Copie de Integer (affectation).\n";
    	return *this;
    }
     
    Integer& Integer::operator+=(const Integer& other)
    {
    	m_data += other.m_data;
    	return *this;
    }
     
    Integer& Integer::operator-=(const Integer& other)
    {
    	m_data -= other.m_data;
    	return *this;
    }
     
    void Integer::operator*=(const Integer& other)
    {
    	m_data *= other.m_data;
    }
     
    Integer operator+(Integer x, const Integer& y)
    {
    	return x += y;
    }
     
    Integer operator-(Integer x, const Integer& y)
    {
    	x -= y;
    	return x;
    }
     
    Integer operator*(Integer x, const Integer& y)
    {
    	x *= y;
    	return x;
    }
    Ma fonction main :
    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
    int _tmain(int argc, _TCHAR* argv[])
    {
    	std::cout << "Test avec l'addition :\n";
    	Integer foo = Integer(1) + Integer(2) + Integer(3);
     
    	std::cout << "\nTest avec la soustraction :\n";
    	Integer bar = Integer(1) - Integer(2) - Integer(3);
     
    	std::cout << "\nTest avec la multiplication :\n";
    	Integer baz = Integer(1) * Integer(2) * Integer(3);
     
    	const Integer un(1);
     
    	std::cout << "\nTest avec l'addition 2 :\n";
    	Integer foo2 = un + Integer(2) + Integer(3);
     
    	std::cout << "\nTest avec la soustraction 2 :\n";
    	Integer bar2 = un - Integer(2) - Integer(3);
     
    	std::cout << "\nTest avec la multiplication 2 :\n";
    	Integer baz2 = un * Integer(2) * Integer(3);
     
    	return 0;
    }
    Sortie :
    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
    Test avec l'addition :
    Copie de Integer (constructeur).
    Copie de Integer (constructeur).
     
    Test avec la soustraction :
    Copie de Integer (constructeur).
    Copie de Integer (constructeur).
     
    Test avec la multiplication :
    Copie de Integer (constructeur).
    Copie de Integer (constructeur).
     
    Test avec l'addition 2 :
    Copie de Integer (constructeur).
    Copie de Integer (constructeur).
    Copie de Integer (constructeur).
     
    Test avec la soustraction 2 :
    Copie de Integer (constructeur).
    Copie de Integer (constructeur).
    Copie de Integer (constructeur).
     
    Test avec la multiplication 2 :
    Copie de Integer (constructeur).
    Copie de Integer (constructeur).
    Copie de Integer (constructeur).

  8. #8
    Membre à l'essai Avatar de neodole
    Homme Profil pro
    Ingénieur après-vente
    Inscrit en
    Avril 2012
    Messages
    32
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur après-vente
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2012
    Messages : 32
    Points : 21
    Points
    21
    Par défaut
    Bonsoir à vous tous,

    Bon je vous remercie chaleureusement pour votre aide mais même avec vos commentaires je n'y arrive pas. J'ai surchargé l'opérateur + et * pour pouvoir additionner et/ou multiplier 2 polynomes et ça marche. Par contre, lorsque je fais la même chose avec l'opérateur += et *= ça ne marche.
    J'ai donc fait au plus simple en utilisant la surcharge de l'opérateur + pour définir la méthode de surcharge de += entre 2 polynomes ce qui donne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    polynome operator+= (polynome P, polynome Q)
    { 
        polynome Res;
    	Res=P+Q;
    }
    Dans mon fichier main.cpp, j'ai mis:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    	//Pour évaluer la surcharge de += mais ça ne marche pas !!!!!
    	cout << P.Eval(2.1) << endl;  // J'évalue le polynome avec une fonction Eval qui calcule le polynome pour x=2.1
    	P+=Q;                                   // J'utilise l'opérateur += entre P et Q 
    	cout << P.Eval(2.1) << endl; // et je réévalue pour voir confirmer le bon fonctionnement de la surcharge de +=
    Quand je fais ça j'ai une erreur sous VSE2010:
    Debug Assertion Failed!
    ......
    ......
    Expression:_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)


    Je ne comprends vraiment pas le problème.

    Avez-vous une idée?

    Merci d'avance

  9. #9
    Membre à l'essai Avatar de neodole
    Homme Profil pro
    Ingénieur après-vente
    Inscrit en
    Avril 2012
    Messages
    32
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur après-vente
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2012
    Messages : 32
    Points : 21
    Points
    21
    Par défaut
    Bon j'ai résolu mon problème en passant sur code block avec lequel je n'ai pas l'erreur. Pour autant, je n'arrive pas à utiliser la surcharge de =+....je ne sais pas pourquoi.

    ....à suivre

  10. #10
    Membre à l'essai Avatar de neodole
    Homme Profil pro
    Ingénieur après-vente
    Inscrit en
    Avril 2012
    Messages
    32
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur après-vente
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2012
    Messages : 32
    Points : 21
    Points
    21
    Par défaut
    J'ai réalisé la surcharge de l'opérateur += via la méthode de classe ci-dessous:
    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
     
    polynome operator+= (polynome P, polynome Q)
    {
    	int degre = max(P.degre,Q.degre);
    	float *coeff;
    	coeff = new float (degre);
    	for (int i=0; i<degre+1; i++)
        {
            if (i<min(P.degre,Q.degre))
            {
                coeff[i]=P.coeff[i]+Q.coeff[i];
            }
            else
            {
                if (P.degre<Q.degre)
                {
                    coeff[i]=Q.degre;
                }
                else
                {
                    coeff[i]=P.degre;
                }
            }
        }
        polynome Res(degre,coeff);
        P.coeff=Res.coeff;
        P.degre=Res.degre;
    	return P;
    }
    Mon problème maintenant c'est que si dans mon fichier main j'écris P+=Q suivi d'un affichage de P et bien P n'a pas pris la valeur de P+Q. En revanche, si je créé un nouveau polynome V(P+=Q), utilisant le constructeur de recopie, et que je visualise V et bien j'ai bien P+Q. De même que si je fais une évaluation pour une valeur de x du polynome à l'aide de la fonction (P+=Q).Eval et bien là aussi ça marche...

    Pourquoi l'utilisation de l'opérateur += ne suffit pas à changer la valeur de P par P+Q ???? c'est une histoire de fou.

    Si quelques à une idée, je suis preneur????

    Merci d'avance
    neodole

  11. #11
    Nouveau membre du Club
    Inscrit en
    Juin 2013
    Messages
    18
    Détails du profil
    Informations forums :
    Inscription : Juin 2013
    Messages : 18
    Points : 35
    Points
    35
    Par défaut
    salut,

    tu as mis (ligne 6) coeff = new float (degre);
    il faut mettre : coeff = new float [degre+1];

    les () vont te donner un seul float dont la valeur initiale est degre
    le +1 : par exemple dan un polynôme de degrés 2 on a 3 coefficients

    d'autre part :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        polynome Res(degre,coeff);  // appel du constructeur de Res
        P.coeff=Res.coeff;              // P.coeff est un pointeur qui va dorénavant pointer sur le tableau de coefs de Res
                                        // l'ancien tableau de coefs de P existe toujours mais tu ne peux plus y acceder : il y a une fuite de memoire
       P.degre=Res.degre;
     	return P;                    // appel du destructeur de Res
                                         // donc maintenant P.degre pointe dans le vide

  12. #12
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 965
    Points
    32 965
    Billets dans le blog
    4
    Par défaut
    Depuis le début ton opérateur += ne modifie pas l'objet courant mais en crée un nouveau.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  13. #13
    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 518
    Points
    41 518
    Par défaut
    Et pourquoi persistes-tu à utiliser des allocations nues plutôt que unique_ptr ou (si tu n'as pas accès à C++11) vector?
    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. #14
    Membre à l'essai Avatar de neodole
    Homme Profil pro
    Ingénieur après-vente
    Inscrit en
    Avril 2012
    Messages
    32
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur après-vente
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2012
    Messages : 32
    Points : 21
    Points
    21
    Par défaut
    Merci pour vos remarques.

    tinofutinofu: Je ne comprends pas ta remarque concernant l'appel au destructeur. Le fait de faire return P ne fait pas appel au destructeur pour moi???

    Boust: c'est effectivement ce que je constate mais la question est pourquoi. Je ne comprends pas.

    Médinoc: je suis des cours de calcul numérique en C++ et c'est mes débuts. On nous a jamais expliquer et/ou montrer l'utilisation de unique_ptr et vector. Je vais regarder.

    Bonne soirée
    neodole

  15. #15
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    739
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 739
    Points : 3 627
    Points
    3 627
    Par défaut
    Citation Envoyé par Pyramidev Voir le message
    Je viens de faire le test avec Visual C++ 2010 Express et je n'observe pas de différence.
    Quand je passe en premier paramètre une lvalue, j'ai une double copie : une pour le premier paramètre et une pour le retour.
    Quand je passe en premier paramètre une rvalue, j'ai une simple copie : une pour le retour.
    La différence se fait sentir en présence du constructeur de mouvement, avec ton code, l'addition utilise le copy-ctor et la soustraction le move-ctor.
    Pour voir l'impact sur la RNVO, le plus classique est avec la post-incrémentation: [c]T x = *this; ++x; return x;[/x] vs return ++T(*this);. La seconde version fait 2 copies.

  16. #16
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 071
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 071
    Points : 12 116
    Points
    12 116
    Par défaut
    Boust: c'est effectivement ce que je constate mais la question est pourquoi. Je ne comprends pas.
    cf. ma réponse qui explique pourquoi votre code ne fait ce que vous attendez.
    L'opérateur "+=" n'a rien de magique, il fait ce que vous avez codé, point barre.
    Si dans l'opérateur "+=", vous tuez des chatons dans le code, bin ça tuera des chatons quand vous appellerez cet opérateur.

    Pour que l'opérateur "+=" fasse ce que vous attendez, suivez les conseils déjà prodiguées dans les multiples réponses.

  17. #17
    Membre à l'essai Avatar de neodole
    Homme Profil pro
    Ingénieur après-vente
    Inscrit en
    Avril 2012
    Messages
    32
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur après-vente
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2012
    Messages : 32
    Points : 21
    Points
    21
    Par défaut
    Pour Bacelar:

    Pas besoin de s'énerver. J'ai clairement des lacunes concernant l'utilisation des classes et des pointeurs. Je dois y remédier et reprendre l'ensemble de vos remarques car je me casse les dents sur ce sujet et je ne m'en sors pas. Ce qui semble clair pour un expert ne l'est pas nécessairement pour un novice comme moi.

    Merci quand même.

    Neodole

  18. #18
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 965
    Points
    32 965
    Billets dans le blog
    4
    Par défaut
    Dès la première réponse de pyramidev la syntaxe de l'opérateur += t'a été donnée T& operator+=(const U& other) { ... return *this; }
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  19. #19
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 470
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 470
    Points : 6 106
    Points
    6 106
    Par défaut
    Citation Envoyé par jo_link_noir Voir le message
    La différence se fait sentir en présence du constructeur de mouvement, avec ton code, l'addition utilise le copy-ctor et la soustraction le move-ctor.
    T'as raison. Je viens de faire le test :
    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
    Test avec l'addition :
    Copie de Integer (constructeur).
    Copie de Integer (constructeur).
     
    Test avec la soustraction :
    Mouvement de Integer (constructeur).
    Mouvement de Integer (constructeur).
     
    Test avec la multiplication :
    Mouvement de Integer (constructeur).
    Mouvement de Integer (constructeur).
     
    Test avec l'addition 2 :
    Copie de Integer (constructeur).
    Copie de Integer (constructeur).
    Copie de Integer (constructeur).
     
    Test avec la soustraction 2 :
    Copie de Integer (constructeur).
    Mouvement de Integer (constructeur).
    Mouvement de Integer (constructeur).
     
    Test avec la multiplication 2 :
    Copie de Integer (constructeur).
    Mouvement de Integer (constructeur).
    Mouvement de Integer (constructeur).

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Surcharge de l'opérateur new
    Par :Bronsky: dans le forum C++
    Réponses: 17
    Dernier message: 27/10/2010, 21h33
  2. Réponses: 8
    Dernier message: 29/08/2006, 00h56
  3. [C#] Surcharge de l'opérateur ==
    Par LE NEINDRE dans le forum Windows Forms
    Réponses: 3
    Dernier message: 18/07/2006, 16h19
  4. Réponses: 6
    Dernier message: 12/07/2006, 15h34
  5. Réponses: 15
    Dernier message: 25/01/2005, 16h51

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