Exploration de surcharge d'opérateur C ++ (5): surcharge d'opérateur d'affectation et fonction d'affectation de copie (copie complète)

Insérez la description de l'image ici
Article précédent: Exploration de la surcharge des opérateurs C ++ (4): La surcharge des opérateurs d'indice est
liée au billet de blog des points de connaissance dans cet article:
C ++ fréquemment cité et copie superficielle explorant
un exemple simple de chaîne de fonctions en C ++ (implémentée dans des fichiers séparés )
Big Three en C ++: recherche sur la construction de copie, l'affectation de copie et le destructeur

Surcharge de l'opérateur d'affectation

Problèmes causés par une copie superficielle :

  Bien qu'un objet puisse être affecté à un autre objet via une instruction d'affectation, comme nous l'avons mentionné précédemment, cette opération peut uniquement créer une copie logique (c'est-à-dire un membre et une copie superficielle du membre). Dans une copie superficielle, un membre d'un objet copie simplement la valeur d'un membre d'un autre objet. Si l'objet contient des membres pointeur , seule la valeur (adresse) de la variable pointeur elle-même est copiée, c'est-à-dire que les membres pointeur des deux objets pointent vers le même espace. Deux problèmes peuvent survenir pour une copie un-à-un des membres pointeurs:
  

(1) Deux membres pointeurs pointent vers le même espace, modifiez l'un d'eux et l'autre change en conséquence. En d'autres termes, les deux objets ne sont pas indépendants l'un de l'autre.
(2) Si deux pointeurs partagent l'espace sur le tas, nous ne savons pas qui est responsable de la libération de cette mémoire. Soit cette mémoire n'a pas été libérée et a provoqué une fuite de mémoire , soit elle a été libérée deux fois et a provoqué une deuxième suppression . non autorisé.

  Par conséquent, s'il existe une variable membre de pointeur dans la classe qui pointe vers l'espace du tas , nous devons généralement surcharger l'opérateur d'affectation pour obtenir une copie complète (copie physique).

Exemple de code de copie superficielle: (acc1 = acc; les pointeurs de titre des deux objets pointent vers le même endroit et le contenu n'est pas indépendant)
Insérez la description de l'image ici
Analyse:
(1) Après avoir modifié le titre de acc1, le titre de acc changera également, vérification de la copie superficielle Le premier problème qui se pose.
(2) Le programme s'est écrasé après l'exécution parce que l'espace de tas pointé par acc1.title a été supprimé lorsque acc1 a été publié, et l'espace de tas pointé par acc.title a été essayé d'être supprimé lorsque acc a été relâché à nouveau, ce qui a entraîné un secondaire. suppression, qui a été vérifiée Le deuxième problème causé par une copie superficielle.

Insérez la description de l'image ici
Joindre un exemple de code:

//小问学编程
#include<iostream>
#include<cstring>
using namespace std;

#define MAX_CHAR 10

class Account
{
    
    
    friend ostream& operator<<(ostream& os,const Account& a);
public:
    Account(const char* new_title="Miss",const char* new_owner="unknown",float new_balance=0.0);
    void changeTitle(const char* new_title);
    void changeOwner(const char* new_owner);
    ~Account();
private:
    char* title;
    char owner[MAX_CHAR];
    float balance;
};

Account::Account(const char* new_title,const char* new_owner,float new_balance)
{
    
    
    title=new char[strlen(new_title)+1];
    strcpy(title,new_title);
    strcpy(owner,new_owner);
    balance=new_balance;
}

void Account::changeTitle(const char* new_title)
{
    
    
    if(strlen(new_title)>strlen(title))
    {
    
    
        delete[]title;
        title=new char[strlen(new_title)+1];
        strcpy(title,new_title);
    }
    else
    {
    
    
        strcpy(title,new_title);

    }
}

void Account::changeOwner(const char* new_owner)
{
    
    
    strcpy(owner,new_owner);
}

Account::~Account()
{
    
    
    delete[] title;
    title=NULL;
}

ostream& operator<<(ostream& os,const Account& a)
{
    
    
    os<<a.title<<" "<<a.owner<<" "<<a.balance<<endl;
    return os;
}

int main()
{
    
    
    Account acc("Lou","Mr",100);
    Account acc1;

    cout<<acc<<acc1;
    acc1=acc;//浅拷贝 相当于acc1.title=acc.title。两个指针指向同一块堆内存
    cout<<acc1;

    acc1.changeOwner("jean");
    cout<<acc<<acc1;//两个对象的owner变量,是各自独立的。

    acc1.changeTitle("Dr");
    cout<<acc<<acc1;

    return 0;
}

résultat de l'opération:

Insérez la description de l'image ici

Solution: copie profonde , lorsque acc est affecté à acc1 (acc1 = acc), les membres pointeurs des deux objets ne peuvent pas pointer vers le même espace, nous devons donc implémenter la surcharge d'opérateur d'affectation de signe égal qui ouvre un autre espace pour copie profonde.
  

Afin d'implémenter la surcharge de l'opérateur d'affectation , nous devons généralement faire cinq choses:

étape1: déterminer s'il s'agit d'une auto-affectation, éviter de s'attribuer un objet à lui-même, si l'objet est attribué à lui-même, nous n'avons généralement pas besoin de faire quoi que ce soit;
étape2: libérer la mémoire pointée à l'origine par le membre pointeur pour éviter la mémoire fuites;
étape3: ouvrir un nouvel espace mémoire pour les membres du pointeur;
étape4: copier le contenu, c'est-à-dire copier le contenu de la rvalue dans la lvalue;
étape5: renvoyer * ceci pour réaliser l'expression de la chaîne.
Insérez la description de l'image ici
Cette fonction est également appelée fonction d'affectation de copie (l'une des trois grandes)

Exemple de code de copie profonde: (vec1 = vec2; la copie complète est réalisée en surchargeant l'opérateur d'affectation) L'
Insérez la description de l'image ici
exemple de code est joint:

//小问学编程
#include<iostream>
using namespace std;

class Vector
{
    
    
public:
    Vector(int s,int an_array[]);//构造函数
	const Vector& operator=(const Vector& x);//拷贝赋值函数	
    ~Vector()//析构函数
    {
    
    
        delete[] rep;//两个独立的指针成员,避免了内存的重复删除
    }
    int get_size() const {
    
    return size;}
    int& operator[](int index) {
    
    return rep[index];}
    const int& operator[](int index) const {
    
    return rep[index];}
private:
    int* rep;//指针成员
    int size;
};

Vector::Vector(int s, int an_array[]):rep(new int[s]),size(s)//构造函数
{
    
    
    for (int i= 0;i<size;++i)
    {
    
    
    rep[i] = an_array[i];
    }
}

const Vector& Vector::operator=(const Vector& x)//拷贝赋值函数	
{
    
    
    if(this != &x) //step 1.避免自赋值
    {
    
    
        size = x.size;
        delete[] rep; 	   //step 2.释放成员指针的旧堆内存
        rep = new int[size];  //step 3.为指针成员开辟新内存空间(堆上)
        for (int i = 0; i < size; ++i)
        {
    
    
            rep[i] = x.rep[i];//step 4.向新内存拷贝内容
        }
    }
    return *this; //step 5.返回*this,即返回新对象本身,即新对象的引用。
}

ostream& operator<<(ostream& os, const Vector& x)//output全局函数
{
    
    
    int s = x.get_size( );
    for (int i = 0; i < s; ++i)
    {
    
    
        os<< x[i]<<" ";
    }
    return os;
}

int main()
{
    
    
    int array1[5] = {
    
    1,2,3,4,5};
    int array2[10] = {
    
    6,7,8,9,10,11,12,13,14,15};
    Vector vec1( 5, array1);
    Vector vec2( 10, array2);
    cout<<vec1<<vec2<<endl;
    vec1 = vec2;//深拷贝的赋值
    cout<<vec1<<vec2<<endl;//此时,两个数组内容虽然一样,但内存中的位置不同。
    vec2[8] = 100;
    cout<<vec1<<vec2<<endl;//对vec2的修改完全不影响vec1的内容。
    return 0;
}

résultat de l'opération:

Cette section n'est pas terminée, à mettre à jour
Exploration de surcharge d'opérateur C ++ (6): opérateur d'appel de fonction surchargé ()

Je suppose que tu aimes

Origine blog.csdn.net/weixin_43297891/article/details/111396128
conseillé
Classement