web-dev-qa-db-fra.com

surcharge de l'opérateur d'affectation en c ++

J'ai utilisé le code suivant pour la surcharge de l'opérateur d'affectation:

SimpleCircle SimpleCircle::operator=(const SimpleCircle & rhs)
{
     if(this == &rhs)
        return *this;
     itsRadius = rhs.getRadius();
     return *this;
}

Mon constructeur de copie est le suivant:

SimpleCircle::SimpleCircle(const SimpleCircle & rhs)
{
    itsRadius = rhs.getRadius();
}

Dans le code de surcharge d'opérateur ci-dessus, le constructeur de copie est appelé car un nouvel objet est en cours de création; j'ai donc utilisé le code ci-dessous:

SimpleCircle & SimpleCircle::operator=(const SimpleCircle & rhs)
{
    if(this == &rhs)
       return *this;
    itsRadius = rhs.getRadius();
    return *this;
}

Cela fonctionne parfaitement et le problème du constructeur de copie est évité, mais y a-t-il des problèmes inconnus (pour moi) à ce sujet?

32
kaushik

Il n'y a aucun problème avec la deuxième version de l'opérateur d'affectation. En fait, c'est la méthode standard pour un opérateur d'affectation.

Edit : Notez que je fais référence au type de retour de l'opérateur d'affectation, pas à l'implémentation elle-même. Comme cela a été souligné dans les commentaires, la mise en œuvre elle-même est un autre problème. Voir ici .

17
juanchopanza

Dans ces circonstances, vous feriez presque certainement mieux de ne pas cocher l'auto-affectation - lorsque vous n'affectez qu'un membre qui semble être un type simple (probablement un double), il est généralement plus rapide de faire cette affectation que d'éviter , donc vous vous retrouveriez avec:

SimpleCircle & SimpleCircle::operator=(const SimpleCircle & rhs)
{
    itsRadius = rhs.getRadius(); // or just `itsRadius = rhs.itsRadius;`
    return *this;
}

Je me rends compte que de nombreux livres anciens et/ou de qualité inférieure conseillent de vérifier l'auto-affectation. Au moins dans mon expérience, cependant, il est suffisamment rare que vous vous en tiriez mieux sans cela (et si l'opérateur en dépend pour l'exactitude, ce n'est certainement pas une exception de sécurité).

En passant, je noterais que pour définir un cercle, vous avez généralement besoin d'un centre et d'un rayon, et lorsque vous copiez ou attribuez, vous souhaitez copier/affecter les deux.

7
Jerry Coffin

Le second est assez standard. Vous préférez souvent renvoyer une référence à partir d'un opérateur d'affectation afin que des instructions comme a = b = c; résoudre comme prévu. Je ne peux penser à aucun cas où je voudrais retourner une copie de la mission.

Une chose à noter est que si vous n'avez pas besoin d'une copie complète, il est parfois préférable d'utiliser le constructeur de copie implicite et l'opérateur d'affectation générés par le compilateur que de lancer le vôtre. Mais à vous de voir ...

Modifier:

Voici quelques appels de base:

SimpleCircle x; // default constructor
SimpleCircle y(x); // copy constructor
x = y; // assignment operator

Supposons maintenant que nous disposions de la première version de votre opérateur d'affectation:

SimpleCircle SimpleCircle::operator=(const SimpleCircle & rhs)
{
     if(this == &rhs)
        return *this; // calls copy constructor SimpleCircle(*this)
     itsRadius = rhs.getRadius(); // copy member
     return *this; // calls copy constructor
}

Il appelle le constructeur de copie et transmet une référence à this afin de construire la copie à renvoyer. Maintenant, dans le deuxième exemple, nous évitons la copie en renvoyant simplement une référence à this

SimpleCircle & SimpleCircle::operator=(const SimpleCircle & rhs)
{
    if(this == &rhs)
       return *this; // return reference to this (no copy)
    itsRadius = rhs.getRadius(); // copy member
    return *this; // return reference to this (no copy)
}
7
AJG85

c'est la bonne façon d'utiliser la surcharge d'opérateur maintenant que vous obtenez votre objet par référence en évitant la copie de valeur.

0
Andy_aka_mol

cela pourrait être utile:

// Operator overloading in C++
//assignment operator overloading
#include<iostream>
using namespace std;

class Employee
{
private:
int idNum;
double salary;
public:
Employee ( ) {
    idNum = 0, salary = 0.0;
}

void setValues (int a, int b);
void operator= (Employee &emp );

};

void Employee::setValues ( int idN , int sal )
{

salary = sal; idNum = idN;

}

void Employee::operator = (Employee &emp)  // Assignment operator overloading function
{
salary = emp.salary;
}

int main ( )
{

Employee emp1;
emp1.setValues(10,33);
Employee emp2;
emp2 = emp1; // emp2 is calling object using assignment operator

}
0
user2808359