C++ operator overloading exploration (5): assignment operator overloading and copy assignment function (deep copy)

Insert picture description here
Previous article: Exploration of C++ operator overloading (4): Subscript operator overloading is
related to the blog post of the knowledge points in this article:
C++ frequent quotes and shallow copy exploring
a simple example of a function chain in C++ (implemented in separate files)
Big Three in C++ : Research on copy construction, copy assignment, and destructor

Assignment operator overloading

Problems caused by shallow copy :

  Although an object can be assigned to another object through an assignment statement, as we mentioned earlier, this operation may only create a logical copy (that is, a member and a shallow copy of the member). In a shallow copy, a member of an object simply copies the value of a member of another object. If the object contains pointer members , only the value (address) of the pointer variable itself is copied, that is, the pointer members of the two objects point to the same space. Two problems may arise for one-to-one copy of pointer members:
  

(1) Two pointer members point to the same space, change one of them, and the other will change accordingly. In other words, the two objects are not independent of each other.
(2) If two pointers share the space on the heap, we don’t know who is responsible for releasing this memory. Either this memory has not been released and caused a memory leak , or it has been released twice and caused a second deletion . not allowed.

  Therefore, if there is a pointer member variable in the class that points to the heap space , we usually need to overload the assignment operator to achieve deep copy (physical copy).

Shallow copy sample code: (acc1 = acc; the title pointers of the two objects point to the same place, and the content is not independent)
Insert picture description here
Analysis:
(1) After modifying the title of acc1, the title of acc will also change, verifying the shallow copy The first problem that arises.
(2) The program crashed after running because the heap space pointed to by acc1.title was deleted when acc1 was released, and the heap space pointed to by acc.title was tried to be deleted when acc was released again, resulting in a secondary deletion, which was verified The second problem caused by shallow copy.

Insert picture description here
Attach example 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;
}

operation result:

Insert picture description here

Solution: Deep copy , when acc is assigned to acc1 (acc1=acc), the pointer members of the two objects cannot be made to point to the same space, so we need to implement the equal sign- assignment operator overloading opens up a separate space for acc. Deep copy.
  

In order to implement overloading of the assignment operator , we usually need to do five things:

step1: Determine whether it is self-assignment, avoid assigning an object to itself, if the object assigns itself to itself, we usually don't need to do anything;
step2: release the memory originally pointed to by the pointer member to avoid memory leaks;
step3: Open up new memory space for pointer members;
step4: copy the content, that is, copy the content of the rvalue to the lvalue;
step5: return *this to realize the chain expression.
Insert picture description here
This function is also called copy assignment function (one of Big Three)

Deep copy sample code: (vec1 = vec2; deep copy is realized by overloading the assignment operator) The
Insert picture description here
sample code is attached:

//小问学编程
#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;
}

operation result:

This section is not finished, to be updated
C++ operator overloading exploration (6): overloaded function call operator ()

Guess you like

Origin blog.csdn.net/weixin_43297891/article/details/111396128