C++ 赋值运算符函数

本文为博主原创文章,未经博主允许不得转载 http://www.cnblogs.com/kiplove/p/6783497.html

C++的重载运算符,由关键字operator和运算符号共同组成,一般而言C++里只要运算符不含"."都可以重载。

这里主要讲一下赋值运算符的重载。

一、一个重载赋值运算符的的例子

class Mystring
{
public:
//    Mystring()=default;
    Mystring(string pData="null")
    {
        m_pData=new string;
        *m_pData=pData;
    }
    Mystring(const Mystring &str)
  {
    
m_pData=new string;
    *m_pData=*str.m_pData;
  }
~Mystring(void){delete m_pData;}
    Mystring& operator=(const Mystring &ptr)
    {
        if(this==&ptr)
            return *this;
        delete m_pData;
        m_pData=NULL;
        m_pData=new string;
        *m_pData=*ptr.m_pData;
        return *this;
    }
    string print(){return *m_pData;}
private:
    string *m_pData;
};

int main()
{
    Mystring a("hello");
    Mystring b,c;
    b=c=a;
//  (b=c)=a;
    cout<<a.print()<<b.print()<<c.print()<<endl;
    return 0;
}

二、分析

1、返回值类型

返回类型一般声明为类型的引用,并在函数结尾时返回实例自身的引用(即*this)。这里主要有两个原因:

a.返回引用可以减少一次拷贝构造和析构函数导致不必要的开销,因为返回值类型不是引用,会创建一个匿名对象,这个匿名对象时个右值,获取return的值。

b.可以实现连续赋值

 在例子中

  b=c=a;

 返回值不是引用类型也是可以的,其运算顺序

  b=(c=a);

 c得到一个右值,再将右值赋给b,所以逻辑上没有问题的。但是如果是

  (b=c)=a;

 这里将会出错,b=c后b是一个右值,所以b=a时将会出错。

2、参数

参数声明为const且是一个引用

a.const 是因为赋值运算,不希望修改原来类的状态,同时可以接受const与非const的参数

b.引用则避免了拷贝构造函数

3、判断是否是传入实例与当前实例是同一个(证同测试),保证自赋值的安全

如果相同,直接返回可以减少不必要的操作

同时防止指向的同一资源一起被销毁。

class Widget{
    ……
    private:
    Bitmap: pb;
}
Widget& Widget::operator=(const Widget& rhs)
{
    delete pb;
    pb=new Bitmap(*rhs.pb);
    return *this;
}
//当出现*this与rhs是同一对象时会出现指向对象被删除

4、赋值前,释放自身的内存

三、考虑异常安全性

异常安全函数保证:

a.不泄露任何资源
b.不允许数据破坏

对于第一点一般可以用资源管理类可以实现,采用智能指针,综合两点保证可以用通过copy-and-swap实现异常安全。

 Mystring& operator=(const Mystring &ptr)
 {
        if(this!=&ptr)
        {
            Mystring temp(ptr);
            string ptemp=*temp.m_pData;
            *temp.m_pData=*m_pData;
            *m_pData=ptemp;
        }
        return *this;
 }

 

原文地址:https://www.cnblogs.com/kiplove/p/6783497.html