本文為博主原創文章,未經博主允許不得轉載 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; }