运算符重载-operator=()函数内容的研究

首先我们引入一个例子:

class C{
   private:
       int r;
       int i;
   public:
    C(int p = 0,int q = 0)
    {
        this->r = p;
        this->i = q;
    }
    void print();
    C(const C& a);
};

类中定义一个print函数输出数据:

void C::print()
    {
        cout<<this->r<<"+"<<this->i<<"i"<<endl;
    }

定义一个拷贝构造函数:

C::C(const C& a)
    {
        cout<<"拷贝构造函数"<<endl;
        this->r = a.r;
        this->i = a.i;
    }

运算符重载等于:
正确的写法:

  C operator= (const C& a)
    {
        cout<<"运算符重载"<<endl;
        this->r = a.r;//2
        this->i = a.i;//3
        return *this;
    }

主函数:

C a(2,2);
C b;
b = a;//等价于b.operator=(a)

(1)调用了对象b的函数,步骤2,3改变了对象b的值,故能够正确输出(这里会和下面讲到的错误写法有关)
(2)对于C operator=(const C& a),的返回值:这里用引用还是直接返回对象?

这里都行,区别就是:
若使用直接返回对象,此时拷贝构造函数(在函数结束前)调用
若使用C&(引用) ,不调用拷贝构造函数

(3)主函数写不同的形式,什么时候调运算符重载?什么时候调拷贝构造?

如果是这样,定义的时候直接赋值:调用拷贝构造
因为拷贝构造,顾名思义,也是构造函数,构造出来给新的对象,而不是已经存在的对象(这是重点!!!!)

在这里,我们可以用正确的解法证实一下,如果拷贝构造是给已经构造的类型,也就是return *this之后,是给的主函数的b的话,那么在拷贝构造函数中,我们在赋值之前,可以打印下,这个值,看看是不是2,如果是2假想正确,然而,打印出来,这是个计算机中的随机数字(如图,这里打印的是1),也就是说,调用的这个拷贝构造,拷贝给了个不知名的区域,而不是给对象b(对象b是已经创建好了的)

运算符重载-operator=()函数内容的研究_第1张图片

拷贝构造下的主函数:

C y(2,2);
C x = y;

运算符重载-operator=()函数内容的研究_第2张图片

如果是赋值:调用运算符重载(可以从定义理解)

• 运算符重载
• 同一个运算符作用于不同类型数据时
• 实现功能相近的操作

运算符重载下的主函数:

C y(2,2);
C x;
x = y;

运算符重载-operator=()函数内容的研究_第3张图片

注意这里,返回的时候调用了拷贝构造函数
这是个错误的operator =()写法:

C operator= (const C& a)
    {
        cout<<"运算符重载"<<endl;
        C s;
        s.r = a.r;
        s.i = a.i;
        s.print();//在函数内输出一下s,确认是否构造成功
        return s;
    }

主函数是这样:
运算符重载-operator=()函数内容的研究_第4张图片

错误写法的输出结果:
运算符重载-operator=()函数内容的研究_第5张图片
这里有两处疑点:
(1)main函数里面的对象b并没有改变

正确的函数重载函数,通过this指针改变了那个要赋值对象的结构
错误的函数重载,没有改变对象结构,在里面新定义了一个对象,然而并没有用,因为返回值返回不是给了要赋值的对象(该对象已经存在),而是个不知名的区域
运算符重载-operator=()函数内容的研究_第6张图片

(2)错误写法中,没有显示调用拷贝构造函数的形式?

:编译器问题,实际上两个返回值都调用了拷贝构造函数,(这里可以修改下编译器设置),根据构造函数的定义,是给新对象,而不是原有对象,所以它重新找了个内存,然后把值给了它
这里x = y 相当于x.operator=(y),调用对象x的函数
那么,如果写 x = (x = y )呢?
测试后 x 还是没有改变,括号中x = y返回的对象,然后作为函数的形参,x 还是没有接收到
运算符重载-operator=()函数内容的研究_第7张图片

运算符重载-operator=()函数内容的研究_第8张图片

为了验证没有接收到的猜想,我们试着print一下返回值
运算符重载-operator=()函数内容的研究_第9张图片

这个operator=函数,单纯使用被赋值功能的话,返回类型完全可以设计成void,因为单纯赋值,你的void那里就表明了你需不需要返回值没啥用
但是如果要实现连续运算(连等),就必须返回类型

综上:
正确的运算符重载函数,函数内部通过this指针改变了那个要赋值对象的结构
错误的函数重载,没有改变对象结构,在里面新定义了一个对象,然而并没有用,因为返回值返回不是给了要赋值的对象,而是个不知名的区域

对于运算符重载的返回值类型:

返回值类型取决于运算符的具体含义:

如果使用运算符的结果产生一个新值,就需要产生一个作为返回值的新对象,这个对
象作为一个常量通过传值方式返回

 Complex operator+(const Complex& a){
Complex result;
result.real = a.real + this->real;
result.imag = a.imag + this->imag;
return result;
}

如果函数返回的是原有对象,通常以引用方式返回,根据是否希望对返回的值进行
运算来决定是否返回const引用。

Complex &operator()(int r, int i){
this->real = r;
this->imag = i;
return *this;
}

你可能感兴趣的:(C++,c++)