C++重载=(赋值运算符)

slime2021-11-08 11:16

在定义的同时进行赋值叫做初始化(Initialization),定义完成以后再赋值(不管在定义的时候有没有赋值)就叫做赋值(Assignment)。初始化只能有一次,赋值可以有多次。

当以拷贝的方式初始化一个对象时,会调用拷贝构造函数;当给一个对象赋值时,会调用重载过的赋值运算符。

即使我们没有显式的重载赋值运算符,编译器也会以默认地方式重载它。默认重载的赋值运算符功能很简单,就是将原有对象的所有成员变量一一赋值给新对象,这和默认拷贝构造函数的功能类似。

对于简单的类,默认的赋值运算符一般就够用了,我们也没有必要再显式地重载它。但是当类持有其它资源时,例如动态分配的内存、打开的文件、指向其他数据的指针、网络连接等,默认的赋值运算符就不能处理了,我们必须显式地重载它,这样才能将原有对象的所有数据都赋值给新对象。

仍然以上节的Array类为例,该类拥有一个指针成员,指向动态分配的内存。为了让Array类的对象之间能够正确地赋值,我们必须重载赋值运算符。请看下面的代码:

#include <iostream>
#include <cstdlib>
using namespace std;
//变长数组类
class Array{
public:
    Array(int len);
    Array(const Array &arr);  //拷贝构造函数
    ~Array();
public:
    int operator[](int i) const { return m_p[i]; }  //获取元素(读取)
    int &operator[](int i){ return m_p[i]; }  //获取元素(写入)
    Array & operator=(const Array &arr);  //重载赋值运算符
    int length() const { return m_len; }
private:
    int m_len;
    int *m_p;
};
Array::Array(int len): m_len(len){
    m_p = (int*)calloc( len, sizeof(int) );
}
Array::Array(const Array &arr){  //拷贝构造函数
    this->m_len = arr.m_len;
    this->m_p = (int*)calloc( this->m_len, sizeof(int) );
    memcpy( this->m_p, arr.m_p, m_len * sizeof(int) );
}
Array::~Array(){ free(m_p); }
Array &Array::operator=(const Array &arr){  //重载赋值运算符
    if( this != &arr){  //判断是否是给自己赋值
        this->m_len = arr.m_len;
        free(this->m_p);  //释放原来的内存
        this->m_p = (int*)calloc( this->m_len, sizeof(int) );
        memcpy( this->m_p, arr.m_p, m_len * sizeof(int) );
    }
    return *this;
}
//打印数组元素
void printArray(const Array &arr){
    int len = arr.length();
    for(int i=0; i<len; i++){
        if(i == len-1){
            cout<<arr[i]<<endl;
        }else{
            cout<<arr[i]<<", ";
        }
    }
}
int main(){
    Array arr1(10);
    for(int i=0; i<10; i++){
        arr1[i] = i;
    }
    printArray(arr1);
   
    Array arr2(5);
    for(int i=0; i<5; i++){
        arr2[i] = i;
    }
    printArray(arr2);
    arr2 = arr1;  //调用operator=()
    printArray(arr2);
    arr2[3] = 234;  //修改arr1的数据不会影响arr2
    arr2[7] = 920;
    printArray(arr1);
   
    return 0;
}

运行结果:

0,1,2,3,4,5,6,7,8,9
0,1,2,3,4
0,1,2,3,4,5,6,7,8,9
0,1,2,3,4,5,6,7,8,9

将arr1赋值给arr2后,修改arr2的数据不会影响arr1。如果把operator=()注释掉,那么运行结果将变为:

0,1,2,3,4,5,6,7,8,9

0,1,2,3,4

0,1,2,3,4,5,6,7,8,9

0,1,2,234,4,5,6,920,8,9

去掉operator=()后,由于m_p指向的堆内存会被free()两次,所以还会导致内存错误。

下面我们就来分析一下重载过的赋值运算符。

1)operator=()的返回值类型为Array&,这样不但能够避免在返回数据时调用拷贝构造函数,还能够达到连续赋值的目的。下面的语句就是连续赋值:

arr4 = arr3 = arr2 = arr1;

2)if(this!=&arr)语句的作用是「判断是否是给同一个对象赋值」:如果是,那就什么也不做;如果不是,那就将原有对象的所有成员变量一一赋值给新对象,并为新对象重新分配内存。下面的语句就是给同一个对象赋值:

arr1 = arr1;
arr2 = arr2;

3)return*this表示返回当前对象(新对象)。

4)operator=()的形参类型为const Array&,这样不但能够避免在传参时调用拷贝构造函数,还能够同时接收const类型和非const类型的实参。

5)赋值运算符重载函数除了能有对象引用这样的参数之外,也能有其它参数。但是其它参数必须给出默认值,例如:

Array & operator=(const Array &arr, int a = 100);

以上就是小编为大家整理的“C++重载=(赋值运算符)”一文,更多相关信息尽在C/C++教程频道。

相关推荐

AI入门,从每个人都应该学的AI第一课开始!

人工智能论文体系,助你快速入门AI

Vue3.0从入门到精通

免责声明:本站所提供的内容均来源于网友提供或网络搜集,由本站编辑整理,仅供个人研究、交流学习使用。如涉及版权问题,请联系本站管理员予以更改或删除。
有用
分享
全部评论快来秀出你的观点
登录 后可发表观点…
发表
暂无评论,快来抢沙发!
算法刷题核心能力提升营