文件memory中第848行 - 975行是auto_ptr的全部定义,如需查看源码请转看本文末尾的附录。auto_ptr的作用不必多说,它在拷贝构造和赋值操作时的“所有权”转移也被人熟知也不再赘述,本文主要是希望通过剖析STL auto_ptr的源码来透视auto_ptr定义背后的思想。
auto_ptr作为比较简单的智能指针,需要处理5种指针行为,接下来我将分别对它们进行阐述。
(1) 构造:
由构造函数来实现,为智能指针指定目标物,即内建指针;默认设目标物为0,从而避免“野指针”带来的错误。构造函数很容易理解,需要警惕的是:如果构造函数是单个参数的,很可能被编译当作隐式类型转换函数来使用。如果你更喜欢完全控制程序的行为,可以禁止编译器悄悄行动,只要用explicit修饰构造函数即可。auto_ptr就采用了这样的方式。
(2) 析构
析构的作用即释放内存空间,由于auto_ptr未引入应用计数,在析构函数中直接释放内存空间即可,不会带来问题。
(3) 拷贝
拷贝即copy constructor,严格说它也应该归纳到构造中去,不过它的行为方式与普通构造有很大的不同。拷贝构造函数的参数是一个智能指针的对象。由于auto_ptr涉及到“所有权”转移问题,因此auto_ptr的拷贝构造函数的形参并没有被修饰为const,因为“所有权”转移将对原对象做修改。
(4) 赋值
赋值即assignment operator,也就是等号操作符。赋值操作符函数的参数也是一个智能指针对象,同样因为“所有权”转移问题并未被修饰为const。赋值操作符函数中需要对智能指针原有的资源进行回收,因此需要先做一个安全性判断然后再释放内存资源。这个过程被封装到release函数中。
(5) 提领
提领即dereference,也称解引用。说白了就是要重载operator*和operator->使智能指针对象有内建指针一样的提领行为。它们的公共操作被封装到get函数中。
以上是最基本的5种指针行为,纵观auto_ptr源码,大部分也是围绕这5种指针行为来编写的,然而有两处可能让你觉得很困扰:
(1) operator auto_ptr<_Other>()函数
(2) auto_ptr_ref结构体
实际上operator auto_ptr<_Other>函数是用来进行隐式类型转换的,由编译器自动调用;auto_ptr_ref是专门用来解决智能指针的右值引用问题,也由编译器自动调用。这个部分的分析说明通用性比较差,如有疑问可以共同交流,这里就容我偷偷懒略去分析了。
附录:STL auto_ptr源码
template<class _Ty>
struct auto_ptr_ref
{ // proxy reference for auto_ptr copying
explicit auto_ptr_ref(_Ty *_Right)
: _Ref(_Right)
{ // construct from generic pointer to auto_ptr ptr
}
_Ty *_Ref; // generic pointer to auto_ptr ptr
};
template<class _Ty>
class auto_ptr
{ // wrap an object pointer to ensure destruction
public:
typedef auto_ptr<_Ty> _Myt;
typedef _Ty element_type;
explicit auto_ptr(_Ty *_Ptr = 0) _THROW0()
: _Myptr(_Ptr)
{ // construct from object pointer
}
auto_ptr(_Myt& _Right) _THROW0()
: _Myptr(_Right.release())
{ // construct by assuming pointer from _Right auto_ptr
}
auto_ptr(auto_ptr_ref<_Ty> _Right) _THROW0()
{ // construct by assuming pointer from _Right auto_ptr_ref
_Ty *_Ptr = _Right._Ref;
_Right._Ref = 0; // release old
_Myptr = _Ptr; // reset this
}
template<class _Other>
operator auto_ptr<_Other>() _THROW0()
{ // convert to compatible auto_ptr
return (auto_ptr<_Other>(*this));
}
/////////////////////////////////////////////////////////////
// 当auto_ptr的拷贝构造函数以及赋值操作符函数的参数是auto_ptr-
// 右值引用对象时,该参数将被转换为 auto_ptr_ref
// 编译器正是通过调用下面的隐式类型转换函数来完成这一隐式转换的
/////////////////////////////////////////////////////////////
template<class _Other>
operator auto_ptr_ref<_Other>() _THROW0()
{ // convert to compatible auto_ptr_ref
_Other *_Cvtptr = _Myptr; // test implicit conversion
auto_ptr_ref<_Other> _Ans(_Cvtptr);
_Myptr = 0; // pass ownership to auto_ptr_ref
return (_Ans);
}
template<class _Other>
_Myt& operator=(auto_ptr<_Other>& _Right) _THROW0()
{ // assign compatible _Right (assume pointer)
reset(_Right.release());
return (*this);
}
template<class _Other>
auto_ptr(auto_ptr<_Other>& _Right) _THROW0()
: _Myptr(_Right.release())
{ // construct by assuming pointer from _Right
}
_Myt& operator=(_Myt& _Right) _THROW0()
{ // assign compatible _Right (assume pointer)
reset(_Right.release());
return (*this);
}
_Myt& operator=(auto_ptr_ref<_Ty> _Right) _THROW0()
{ // assign compatible _Right._Ref (assume pointer)
_Ty *_Ptr = _Right._Ref;
_Right._Ref = 0; // release old
reset(_Ptr); // set new
return (*this);
}
~auto_ptr()
{ // destroy the object
delete _Myptr;
}
_Ty& operator*() const _THROW0()
{ // return designated value
#if _ITERATOR_DEBUG_LEVEL == 2
if (_Myptr == 0)
_DEBUG_ERROR("auto_ptr not dereferencable");
#endif /* _ITERATOR_DEBUG_LEVEL == 2 */
return (*get());
}
_Ty *operator->() const _THROW0()
{ // return pointer to class object
#if _ITERATOR_DEBUG_LEVEL == 2
if (_Myptr == 0)
_DEBUG_ERROR("auto_ptr not dereferencable");
#endif /* _ITERATOR_DEBUG_LEVEL == 2 */
return (get());
}
_Ty *get() const _THROW0()
{ // return wrapped pointer
return (_Myptr);
}
_Ty *release() _THROW0()
{ // return wrapped pointer and give up ownership
_Ty *_Tmp = _Myptr;
_Myptr = 0;
return (_Tmp);
}
void reset(_Ty *_Ptr = 0)
{ // destroy designated object and store new pointer
if (_Ptr != _Myptr)
delete _Myptr;
_Myptr = _Ptr;
}
private:
_Ty *_Myptr; // the wrapped object pointer
};
分享到:
相关推荐
最新的STL源码,最新的STL源码,最新的STL源码
stlshow_stl分层_STL分层_stlmatlab_STL切片_stl分层_源码.rar.rar
STL在liunx下的源代码文件,可以在Linux下安装,也可以直接阅读源码来学习STL编程
stlshow_stl分层_STL分层_stlmatlab_STL切片_stl分层.zip
STL源码,所有STL源码程序都在眼下,希望你能学会
用于三维光学形貌扫描完成后,生成的stl文件的读取,并形成俯视投影云图
STL课件_C++_课件stl_c++课件_源码.zip
STL源码_侯捷注释,相信大家都有看过侯捷的STL的源码解析那本书吧。 这是STL的注释
代码中包含了部分作者侯捷的<<STL源码剖析>>一书中的程序实例,有助于理解及应用STL,来进行方便高效的编程
标准模板库的源码剖析,一本很不错的c++模板库的分析书
C++读取STL文件,输出所有三角形的顶点坐标
stl源码剖析stl源码剖析stl源码剖析stl源码剖析stl源码剖析stl源码剖析stl源码剖析
读取二进制stl文件,并计算3d模型的体积
侯捷_STL源码分析_STLsource(JJhou)
上传stl文件,等到模型的体积、尺寸等参数
西门子S7-300语句表 STL 实例源代码
#ifndef __SGI_STL_INTERNAL_ALGOBASE_H #define __SGI_STL_INTERNAL_ALGOBASE_H #ifndef __STL_CONFIG_H #include <stl_config.h> #endif #ifndef __SGI_STL_INTERNAL_RELOPS #include <stl_relops.h> #endif #...
用于STL文件读取与显示的C语言程序,简单方便实用。
VC++利用动态连接库开发的读取STL格式文件的界面,可鼠标点选,旋转物体,有需要的朋友可以下载
读取 点云数据 STL 文件 分块化编程