类的四个默认成员函数->赋值运算符重载函数

4.赋值运算符重载函数

1.函数的作用,参数和返回值

1.作用

  赋值运算符重载函数用于类对象的赋值操作,当我们未实现该函数时,编译器会自动为我们实现该函数。

2.参数

  赋值运算符重载函数的参数是常引用类型的类类型,声明为常量的好处是可以接受常量参数和非常量参数,

声明为引用类型使得参数没有了临时对象的生成,减少了一次拷贝构造的发生

3.返回值

  大部分人(包括Effective C++)认为赋值运算符重载函数的返回值为引用类型的*this,这样可以实现支持赋值的连锁形式。举个栗子:  

class A
{
public:
    A(){}
    A(int _a,int _b) : a(_a),b(_b){}
    A &operator =(const A&rhs)
    {
        this->a = rhs.a;
        this->b = rhs.b;
        return *this;
    }
public:
    int a;
    int b;
};

int main()
{
    A j(12,13);
    A k,l;
    k = l = j;
    cout << j.a << "," << j.b << endl;
    cout << k.a << "," << k.b << endl;
    cout << l.a << "," << j.b << endl;
    return 0;
}

测试结果:12,13

12,13

12,13

  那么,这种说法是否正确呢?我们来做测试。

class B
{
public:
    B(){}
    
    B(int _a,int _b) : a(_a),b(_b){}
    B operator =(const B&rhs)
    {
        this->a = rhs.a;
        this->b = rhs.b;
        return *this;
    }
public:
    int a;
    int b;
};
int main()
{
    B j(12,13);
    B k,l,n;
    //n = k = l = j = B(90,80);
    n = k = l = j;
    cout << j.a << "," << j.b << endl;
    cout << k.a << "," << k.b << endl;
    cout << l.a << "," << j.b << endl;
    cout << n.a << "," << n.b << endl;
    return 0;
}

测试结果:

12,13

12,13

12,13

12,13

  测试结果表明,赋值运算符重载函数并不需要返回值为引用类型,也可以完成连续赋值。那么,返回值为引用类型有什么好处呢?

如果返回值不是引用,在赋值操做中,必然会产生临时对象来完成对象的赋值操作。看代码

class B
{
public:
    B(){}
    B(const B&rhs)
    {
        this->a = rhs.a;
        this->b = rhs.b;
        std::cout << "copy constructors" << std::endl;
    }
    B(int _a,int _b) : a(_a),b(_b){}
    B operator =(const B&rhs)
    {
        this->a = rhs.a;
        this->b = rhs.b;
        return *this;
    }
public:
    int a;
    int b;
};
int main()
{
    B j(12,13);
    B k,l,n;
    //n = k = l = j = B(90,80);
    n = k = l = j;
    cout << j.a << "," << j.b << endl;
    cout << k.a << "," << k.b << endl;
    cout << l.a << "," << j.b << endl;
    cout << n.a << "," << n.b << endl;
    return 0;
}

测试结果:

copy constructors

copy constructors

copy constructors

12,13

12,13

12,13

12,13

注:此栗子经过vs2010与gcc共同测试,结果相同!!!

  我们注意到,当返回值类型不为引用类型时,会产生临时对象,这样就会产生拷贝构造的多次调用,浪费了空间和效率!!!

所以,赋值运算符的重载不一定是引用类型也可以实现类对象的连续赋值,但返回引用类型在效率上是最佳的。

2.处理自赋值

  在实现赋值运算符重载时,要考虑自赋值的问题,考虑一种情况,当构造函数中调用new在堆上开辟空间时,我们要考虑深拷贝的情况,

那么这种做法似乎是合理的。

Widget& Widget::operator=(const Widget &rhs)
{
     delete pb;
     pb = new Bitmap(*rhs.pb);
     return *this;          
}

如果这时,该类的对象发生了自赋值,那么结果是致命的!delete掉了自身的Bitmap,使得自己的一个指针成员指向一个已经被删除的对象!!!

 

posted @ 2017-03-22 22:08  是召不是昭  阅读(1324)  评论(0编辑  收藏  举报