陷阱重重的C++赋值重载函数operator=
曾经有C++高手说过:看一个C++程序员功底是否够硬,让他写个赋值重载函数就能看出来了!在我看来,这种说法并不夸张。因为能将operator=函数写好确实需要扎实的基础,其中的陷阱真不少。
- 陷阱一:不懂规避自我拷贝
先看代码
string& string::operator=(const string& rhs) { if (m_pStr != NULL) delete [] m_pStr; m_pStr = new char[....]; strcpy(....); return *this; }
此代码就是没有规避自我赋值,那么如果进行以下的调用,那么后果很严重。
string myStr("abc"); myStr = myStr;
赋值操作中,会先把自己的数据delete掉,然后再strcpy一个空值,程序立马挂了。
所以,在赋值函数开始的时候,需要防止自我复制。写法如下:
string& string::operator=(const string& rhs) { // 防止自我赋值 if (this == &rhs) return * this; ... }但有些书籍上面使用以下写法,不敢苟同。
string& string::operator=(const string& rhs) { // 防止自我赋值 if (*this == rhs) // 这只是判断内容是否相同,并不能判定是自我赋值!!! return * this; ... }
- 陷阱二:返回值的类型用啥
在初学者的群体当中,有出现诸如以下几种返回值版本:
// 版本一 string string::operator=(const string& rhs) { ... return * this; }或
// 版本二 const string& string::operator=(const string& rhs) { ... return * this; }或
// 版本三 string* string::operator=(const string& rhs) { ... return this; }
版本一的缺陷:多了一个临时对象的生成和拷贝,影响程序效率。
版本二的缺陷:非const类型的变量想得到它的连续赋值变得不可能,而且编译器也会报错。
版本三的缺陷:不能保持连续赋值时类型的统一性,违反了编程的惯例。如
// 版本三的缺陷 string a, b, c; *a = b = c; // 必须这样赋值给a,类型不统一!!
- 陷阱三:未做深拷贝
任何未做深拷贝的版本都退化为默认版本。
string& string::operator=(const string& rhs) { if (this == &rhs) return *this; if (m_pStr != NULL) delete [] m_pStr; m_pStr = rhs.m_pStr; // 浅拷贝 return *this; }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。