关于auto_ptr
2015-03-10 13:21
225 查看
智能指针auto_ptr 在我理解是用一个对象来管理原生指针,通过拥有权Owns的控制,在智能指针对象析构时来释放原生指针的空间,以此来保证内存总是被释放掉,避免内存泄露。
拷贝构造函数
当用一个智能指针拷贝构造另一个智能指针时,要考虑,如果在构造新的对象时只进行“浅拷贝”
_Owns=_Y._Owns;
_Ptr=_Y._Ptr;
这样会造成两个只能指针同时指向同一块内存且同时有拥有权,在这两个对象析构时会对同一块内存释放两次引发错误。
在成员初始化类表中先对_Owns赋值之后再对_Ptr赋值 并同时调动release()函数将_Y._Owns赋值为false,如果Y有拥有权,那么新对象将获得拥有权,然后Y失去拥有权,这样就避免两个对象对同一块内存都有拥有权的错误。但如果写成这样
也就是说_Owns(_Y._Owns)总是在_Ptr(_Y.release())前执行,因为成员初始化的顺序只与成员声明顺序有关与其在初始化列表中的顺序无关。
赋值构造
int *p = new int(3);
auto_ptr<int> p2(p);
auto_ptr<int> p3(p2);//p2._Owns为false
auto_ptr<int> p4(p);
p4=p2;//////////////////////////在这用一个对p所指向空间没有拥有权的p2来给p4赋值,最后得到结果p4却是对此空间有拥有权的。。。 但如果p4也被赋值成无拥有权,那么又会有内存泄露,然后再想,那在被赋值前先释放掉那块内存好了,免得发生泄露,但这样做的结果是 经过这样的以此赋值,两个只能指针都指向了一块已经被释放的内存。源码这样写还是有他的道理的。
释放函数
释放拥有权并返回指针
那既然要修改_Owns直接去掉const就好了 不用这么麻烦 。网上看会发现 在拷贝构造函数和赋值构造函数中都调用了_Y.release(),并且为了安全性考虑 参数_Y是一个常引用方式传进来的,所以_Y只能调用常方法,release()const 这个const是不能去掉的。
这时就需要在常方法中来改变成员变量,上边的强制类型转换是一种方法还可以通过关键字mutable来实现,mutalbe的意思是“可变的”,跟const是反义词。mutable是为了突破const的限制而设置的。被mutable修饰的变量将永远处于可变的状态,即使在一个const函数中。
private:
mutable bool _Owns;
_Ty *_Ptr;
<span style="font-size:14px;">template<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; };</span>
拷贝构造函数
<span style="font-size:14px;">auto_ptr(const auto_ptr<_Ty>& _Y) _THROW0() : _Owns(_Y._Owns), _Ptr(_Y.release()) {}</span>
当用一个智能指针拷贝构造另一个智能指针时,要考虑,如果在构造新的对象时只进行“浅拷贝”
_Owns=_Y._Owns;
_Ptr=_Y._Ptr;
这样会造成两个只能指针同时指向同一块内存且同时有拥有权,在这两个对象析构时会对同一块内存释放两次引发错误。
在成员初始化类表中先对_Owns赋值之后再对_Ptr赋值 并同时调动release()函数将_Y._Owns赋值为false,如果Y有拥有权,那么新对象将获得拥有权,然后Y失去拥有权,这样就避免两个对象对同一块内存都有拥有权的错误。但如果写成这样
<span style="font-size:14px;">auto_ptr(const auto_ptr<_Ty>& _Y) _THROW0() :<span style="font-family: Arial, Helvetica, sans-serif;">_Ptr(_Y.release())</span>,_Owns(_Y._Owns), {}</span>看起来是Y先失去拥有权,再对_Owns赋值,似乎_Owns总是false.但在我自己写这个auto_ptr时确实把拷贝构造写成了上面的样子,但_Owns仍能被正确赋值。
也就是说_Owns(_Y._Owns)总是在_Ptr(_Y.release())前执行,因为成员初始化的顺序只与成员声明顺序有关与其在初始化列表中的顺序无关。
<span style="font-size:14px;">private: bool _Owns; _Ty *_Ptr;</span>_Owns的初始化总早于_Ptr
赋值构造
<span style="font-size:14px;">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); }</span>当用一个智能指针对象赋值另一个智能指针对象时同样要考虑_Owns的问题,不能两个对象对同一块内存都有拥有权,同时还要考虑被修改的这个指针原来管理的那块内存要释放掉。但源码中这种写法有一个小问题
int *p = new int(3);
auto_ptr<int> p2(p);
auto_ptr<int> p3(p2);//p2._Owns为false
auto_ptr<int> p4(p);
p4=p2;//////////////////////////在这用一个对p所指向空间没有拥有权的p2来给p4赋值,最后得到结果p4却是对此空间有拥有权的。。。 但如果p4也被赋值成无拥有权,那么又会有内存泄露,然后再想,那在被赋值前先释放掉那块内存好了,免得发生泄露,但这样做的结果是 经过这样的以此赋值,两个只能指针都指向了一块已经被释放的内存。源码这样写还是有他的道理的。
释放函数
<span style="font-size:14px;">_Ty *release() const _THROW0() {((auto_ptr<_Ty> *)this)->_Owns = false; return (_Ptr); }</span>
释放拥有权并返回指针
<span style="font-size:14px;">((auto_ptr<_Ty> *)this)->_Owns = false;</span>那这语句为什么要进行强制类型转换,是为了去掉this指针的常性,从而能再const修饰的成员函数中修改_Owns
那既然要修改_Owns直接去掉const就好了 不用这么麻烦 。网上看会发现 在拷贝构造函数和赋值构造函数中都调用了_Y.release(),并且为了安全性考虑 参数_Y是一个常引用方式传进来的,所以_Y只能调用常方法,release()const 这个const是不能去掉的。
这时就需要在常方法中来改变成员变量,上边的强制类型转换是一种方法还可以通过关键字mutable来实现,mutalbe的意思是“可变的”,跟const是反义词。mutable是为了突破const的限制而设置的。被mutable修饰的变量将永远处于可变的状态,即使在一个const函数中。
private:
mutable bool _Owns;
_Ty *_Ptr;
相关文章推荐
- 关于auto_ptr_ref的一点问题
- 《The C++ Standard Library》第50页 关于传递auto_ptr的问题
- 关于auto_ptr_ref的一点问题
- 关于std:auto_ptr std:shared_ptr std:unique_ptr
- 关于内存泄漏---auto_ptr
- 关于auto_ptr
- 关于auto_ptr
- 关于C++中的auto_ptr
- 关于std:auto_ptr
- 关于auto_ptr的使用
- 关于std:auto_ptr
- 关于class auto_ptr
- 关于智能指针auto_ptr
- 关于auto_ptr_ref的一点问题
- 条款13:关于文中多次提及的auto_ptr和shared_ptr
- [C++标准模板库:自修教程与参考手册]关于auto_ptr
- 关于auto_ptr的一些事
- 关于auto_ptr_ref的一点问题
- 关于智能指针 auto_ptr
- 关于auto_ptr使用的一些随感