C++的重载赋值运算符
我们在定义类的时候编译器会自动创建对赋值运算符的重载,但类似拷贝构造函数,这个重载函数也只是对值的拷贝,如果类中有在堆区开辟的空间则需要实现深拷贝。
1 #include<iostream> 2 using namespace std; 3 4 //定义类型CMyString 5 class CMyString 6 { 7 public: 8 CMyString(char* pData = nullptr); 9 10 //重载赋值运算符 11 CMyString& operator=(const CMyString &str); 12 13 ~CMyString(void); 14 15 private: 16 char* m_pData; 17 }; 18 19 CMyString::CMyString(char* pData = nullptr) 20 { 21 int len = strlen(pData); 22 this->m_pData = (char*)malloc(sizeof(char)*(len + 1)); 23 memset(m_pData, '\0', sizeof(char)*(len + 1)); //将\0赋值给m_pData,长度为第三个参数大小 24 strcpy(m_pData, pData); 25 } 26 27 28 //重载赋值运算符 29 //为实现链式赋值,返回值需要是本身,另外为减少拷贝构造,返回的为CMyString& 30 CMyString& CMyString::operator=(const CMyString &str) 31 { 32 //如果赋值的两个对象是同一个,则不能赋值 33 if (&str == this) 34 return *this; 35 36 //从堆区开辟新的空间时,首先释放之前的空间 37 if (this->m_pData != NULL) 38 { 39 delete[] this->m_pData; 40 this->m_pData = NULL; 41 } 42 43 //从堆区开辟新的空间 44 this->m_pData = new char[strlen(str.m_pData)+1]; 45 strcpy(m_pData, str.m_pData); 46 47 //返回自身 48 return *this; 49 } 50 51 CMyString::~CMyString(void) 52 { 53 if (this->m_pData != NULL) 54 { 55 delete this->m_pData; 56 this->m_pData = NULL; 57 } 58 }
重载赋值运算符时主要需要考虑下面几点:
- 为了实现链式赋值操作,函数的返回值应该是其自身,另外为了节省拷贝构造的花销,返回值类型应该是其自身的应用,在上面案例中为CString&;
- 为防止参数在重载函数中发生变化,传入的参数类型应该是常量引用;
- 在申请堆区空间之前应该考虑是否需要先释放自身之前在堆区所占用的空间;
- 在实现深拷贝之前首先应该判断赋值的两个对象是不是相同的,如果是相同的应该直接返回。若没有考虑到相同的情况,那么在释放自身空间的时候会出现问题,即已经被释放的空间再次被拿来赋值自身;
- 返回值应该是*this.