Effective C++条款11解读: 在operator=中处理“自我赋值”------顺便给出string类的Big Three
来源:互联网 发布:阿里云市场镜像安全吗 编辑:程序博客网 时间:2024/04/29 11:17
我们先看一个简单的string程序:
#include <iostream>using namespace std;class TaogeString{private:char *m_p;public:TaogeString(char *p = NULL){if(NULL == p){m_p = new char[1];m_p[0] = '\0';}else{int len = strlen(p);m_p = new char[len + 1];strcpy(m_p, p);}}TaogeString(const TaogeString &a){int len = strlen(a.m_p);m_p = new char[len + 1];strcpy(m_p, a.m_p);}TaogeString& operator=(const TaogeString &a) {delete m_p;int len = strlen(a.m_p);m_p = new char[len + 1];strcpy(m_p, a.m_p);return *this;}~TaogeString(){delete []m_p;m_p = NULL;}void print(){cout << m_p << endl;}};int main(){TaogeString a("good");TaogeString b("");b = a;b.print();return 0;}运行一下, 结果为:
good
其实, 上面程序是有问题的, 不信, 请看:
#include <iostream>using namespace std;class TaogeString{private:char *m_p;public:TaogeString(char *p = NULL){if(NULL == p){m_p = new char[1];m_p[0] = '\0';}else{int len = strlen(p);m_p = new char[len + 1];strcpy(m_p, p);}}TaogeString(const TaogeString &a){int len = strlen(a.m_p);m_p = new char[len + 1];strcpy(m_p, a.m_p);}TaogeString& operator=(const TaogeString &a) {delete m_p;int len = strlen(a.m_p);m_p = new char[len + 1];strcpy(m_p, a.m_p);return *this;}~TaogeString(){delete []m_p;m_p = NULL;}void print(){cout << m_p << endl;}};int main(){TaogeString a("good");a = a; // 自我赋值a.print();return 0;}结果, a对应的是一个垃圾值? 为什么呢? 我们看看operator=函数就清楚了, 没有处理自我赋值, 导致a中指针指向的堆被释放了。 有的朋友可能说: 谁他妈无聊去自我赋值啊? 其实, 自我赋值的情况还是很普遍的, 比如x[i] = x[j], 当i和j相等的时候, 就自然而然是自我赋值了。 所以, 为了程序的健壮性, 必须考虑自我赋值。 上面的程序改为:
#include <iostream>using namespace std;class TaogeString{private:char *m_p;public:TaogeString(char *p = NULL){if(NULL == p){m_p = new char[1];m_p[0] = '\0';}else{int len = strlen(p);m_p = new char[len + 1];strcpy(m_p, p);}}TaogeString(const TaogeString &a){int len = strlen(a.m_p);m_p = new char[len + 1];strcpy(m_p, a.m_p);}TaogeString& operator=(const TaogeString &a) {if(&a == this) // 处理自我赋值{return *this;}delete m_p;int len = strlen(a.m_p);m_p = new char[len + 1];strcpy(m_p, a.m_p);return *this;}~TaogeString(){delete []m_p;m_p = NULL;}void print(){cout << m_p << endl;}};int main(){TaogeString a("good");a = a; // 自我赋值a.print();return 0;}结果为:
good
这样就好了。
如果大家熟悉STL源码, 就可以到处见到这种自我赋值的防护机制。 之前, 我们剖析过auto_ptr的源码, 其中也有自我赋值的处理, 下面, 我们再次把这个源码拿过来, 放在下面, 作为本文的终结,让我们再次看看微软式的风骚代码:
// TEMPLATE CLASS auto_ptrtemplate<class _Ty>class auto_ptr {public:typedef _Ty element_type;explicit auto_ptr(_Ty *_P = 0) _THROW0(): _Owns(_P != 0), _Ptr(_P) {}auto_ptr(const auto_ptr<_Ty>& _Y) _THROW0(): _Owns(_Y._Owns), _Ptr(_Y.release()) {}auto_ptr<_Ty>& operator=(const auto_ptr<_Ty>& _Y) _THROW0(){if (this != &_Y) {if (_Ptr != _Y.get()){if (_Owns)delete _Ptr;_Owns = _Y._Owns; }else if (_Y._Owns)_Owns = true;_Ptr = _Y.release(); }return (*this); }~auto_ptr(){if (_Owns)delete _Ptr; }_Ty& operator*() const _THROW0(){return (*get()); }_Ty *operator->() const _THROW0(){return (get()); }_Ty *get() const _THROW0(){return (_Ptr); }_Ty *release() const _THROW0(){((auto_ptr<_Ty> *)this)->_Owns = false;return (_Ptr); }private:bool _Owns;_Ty *_Ptr;};
本文到此为止。
0 0
- Effective C++条款11解读: 在operator=中处理“自我赋值”------顺便给出string类的Big Three
- 【Effective c++】条款11:在operator=中处理“自我赋值”
- 《Effective C++》学习笔记条款11 在operator =中处理“自我赋值”
- Effective C++——》条款11:在operator=中处理自我赋值
- Effective C++:条款11:在operator= 中处理“自我赋值”。
- Effective C++ 条款11 在赋值操作符operator=中处理“自我赋值”
- 读书笔记《Effective C++》条款11:令operator=中处理”自我赋值“
- Effective C++ 读书笔记 条款11:在operator= 中处理"自我赋值"
- 条款11: 在operator= 中处理"自我赋值"
- 条款11:在operator= 中处理“自我赋值”
- 条款11: 在operator= 中处理"自我赋值"
- 条款11:在operator = 中处理"自我赋值"
- 条款11:在operator=中处理“自我赋值”
- 条款11:在operator=中处理”自我赋值“
- 总结条款:11在operator=中处理“自我赋值”
- 条款11 在operator=中处理“自我赋值”
- 条款11:在operator=中处理“自我赋值”
- 条款11 在operator=中处理“自我赋值“
- Android笔记之SeekBar自定义样式与监听
- 数据库回顾(三)—触发器
- 用Dart搭建HTTP服务器(1)
- [iOS]Error Domain=NSURLErrorDomain Code=-1005 “The network connection was lost.”
- Android intent传递参数
- Effective C++条款11解读: 在operator=中处理“自我赋值”------顺便给出string类的Big Three
- pooing在CNN框架中
- Lucene4.10使用教程(四):lucene的Search
- 红色高跟鞋
- 通过Java反射在运行时修改TimerTask的执行周期并且立即生效
- ASM(二) 利用Core API 变更类成员
- apk文件的修改及签名
- MyBatis学习(一)- 搭建MyBatis项目
- LeetCode 之 Linked List Cycle I II — C++ 实现