boost 源码 ref 库分析
2014-02-13 22:40
351 查看
引用文件: boost/ref.hpp
一般情况下,泛型算法中的函数对象,传值语义是可行的,但是也有很多特殊情况,作为参数的函数对象拷贝代价过高(具有复杂的内部状态),或者不希望拷贝对象(内部状态不应该被改变),甚至拷贝是不可行的(noncopyable,单件)。
boost.ref应用代理模式,引入对象引用的包装器概念解决了这个问题。
从代码中可以看出,其实就是保存了所封装的对象的指针。所以可以达到拷贝甚至快速拷贝的目的。
boost::addressof 的实现就是取该对象的地址。
boost::detail::addr_impl_ref 简单的对象封装。不可赋值拷贝。而addressof_impl的实现如下
f函数的实现,如此费工夫转换来转换去,目的是防止自定义的operator T*() 的操作符重载。
reference_wrapper的名字过长,声明引用包装对象很不方便,因而ref库提供了两个便捷的工厂函数ref() 和 cref(),可以通过参数类型推导很容易的构造reference_wrapper对象。
参见如下示例。
看看ref()的定义
简单的封装,
解封装函数unwrap_ref定义如下
因为返回值是不参与类型推演的。所以有了unwrap_reference模板,另外typename关键字不能少,否则type会被当作unwrap_reference的成员变量,而不是一个类型。
【补】对于这个例子
以上分析权当学习笔记以记之。
一般情况下,泛型算法中的函数对象,传值语义是可行的,但是也有很多特殊情况,作为参数的函数对象拷贝代价过高(具有复杂的内部状态),或者不希望拷贝对象(内部状态不应该被改变),甚至拷贝是不可行的(noncopyable,单件)。
boost.ref应用代理模式,引入对象引用的包装器概念解决了这个问题。
template<class T> class reference_wrapper { public: typedef T type; #if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, < 1300 ) explicit reference_wrapper(T& t): t_(&t) {} #else explicit reference_wrapper(T& t): t_(boost::addressof(t)) {} #endif operator T& () const { return *t_; } T& get() const { return *t_; } T* get_pointer() const { return t_; } private: T* t_; };
从代码中可以看出,其实就是保存了所封装的对象的指针。所以可以达到拷贝甚至快速拷贝的目的。
boost::addressof 的实现就是取该对象的地址。
template<class T> T * addressof( T & v ) { #if (defined( __BORLANDC__ ) && BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x610 ) ) ) || defined( __SUNPRO_CC ) return boost::detail::addressof_impl<T>::f( v, 0 ); #else return boost::detail::addressof_impl<T>::f( boost::detail::addr_impl_ref<T>( v ), 0 ); #endif }
boost::detail::addr_impl_ref 简单的对象封装。不可赋值拷贝。而addressof_impl的实现如下
template<class T> struct addressof_impl { static inline T * f( T & v, long ) { return reinterpret_cast<T*>( &const_cast<char&>(reinterpret_cast<const volatile char &>(v))); } static inline T * f( T * v, int ) { return v; } };
f函数的实现,如此费工夫转换来转换去,目的是防止自定义的operator T*() 的操作符重载。
reference_wrapper的名字过长,声明引用包装对象很不方便,因而ref库提供了两个便捷的工厂函数ref() 和 cref(),可以通过参数类型推导很容易的构造reference_wrapper对象。
参见如下示例。
VECINT vecInt; int intArray[] = {2,3,4,5,6,7,8,9}; vecInt.assign(intArray,intArray+_countof(intArray)); reference_wrapper<std::vector<int>> rw1 = boost::ref(vecInt); BOOST_AUTO(rw1,boost::ref(vecInt)); if(is_reference_wrapper<BOOST_TYPEOF(rw1)>::value) std::cout << typeid(rw1).name() << std::endl; std::cout << rw1.get()[0] << std::endl; std::cout << unwrap_ref(rw1)[1] << std::endl;
看看ref()的定义
template<class T> inline reference_wrapper<T> BOOST_REF_CONST ref(T & t) { return reference_wrapper<T>(t); }
简单的封装,
解封装函数unwrap_ref定义如下
template <class T> inline typename unwrap_reference<T>::type& unwrap_ref(T& t) { return t; }
因为返回值是不参与类型推演的。所以有了unwrap_reference模板,另外typename关键字不能少,否则type会被当作unwrap_reference的成员变量,而不是一个类型。
【补】对于这个例子
std::cout << unwrap_ref(rw1)[1] << std::endl;按上面的源码解释不通,看样子是返回reference_wrapper,是不能直接[]操作,通过再次阅读源码发现有如下宏:
# define AUX_REFERENCE_WRAPPER_METAFUNCTIONS_DEF(X) \ template<typename T> \ class is_reference_wrapper< X > \ : public mpl::true_ \ { \ }; \ \ template<typename T> \ class unwrap_reference< X > \ { \ public: \ typedef T type; \ }; \ /**/ AUX_REFERENCE_WRAPPER_METAFUNCTIONS_DEF(reference_wrapper<T>) #if !defined(BOOST_NO_CV_SPECIALIZATIONS) AUX_REFERENCE_WRAPPER_METAFUNCTIONS_DEF(reference_wrapper<T> const) AUX_REFERENCE_WRAPPER_METAFUNCTIONS_DEF(reference_wrapper<T> volatile) AUX_REFERENCE_WRAPPER_METAFUNCTIONS_DEF(reference_wrapper<T> const volatile) #endif可以看出,通过返回值的偏特化,获取里面最原始的类型。
以上分析权当学习笔记以记之。
相关文章推荐
- int av_packet_ref(AVPacket *dst, const AVPacket *src)源码分析
- cocos2d-x 源码分析 : Ref (CCObject) 源码分析 cocos2d-x内存管理策略
- boost::mpl::vector(GCC)源码分析
- boost tss.hpp源码分析
- x264源码分析 -- get_ref
- 函数适配器bind2nd 、mem_fun_ref 源码分析、函数适配器应用举例
- boost.asio源码剖析(三) ---- 流程分析
- 从零开始学C++之boost库(一):详解 boost 库智能指针(scoped_ptr<T> 、shared_ptr<T> 、weak_ptr<T> 源码分析)
- BOOST_PP_LOCAL_ITERATE() (局部迭代) 源码分析
- 从零开始学C++之STL(九):函数适配器bind2nd 、mem_fun_ref 源码分析、函数适配器应用举例
- 【C++】Android (Light)RefBase-sp-wp引用计数-智能指针源码分析
- 详解 boost 库智能指针(scoped_ptr<T> 、shared_ptr<T> 、weak_ptr<T> 源码分析)
- [置顶] 从零开始学C++之boost库(一):详解 boost 库智能指针(scoped_ptr<T> 、shared_ptr<T> 、weak_ptr<T> 源码分析)
- 决策树(七)--Boost及源码分析
- boost:asio信号量signal_set源码分析及使用
- boost::filesystem::resize_file函数的源码分析
- cocos2d-x 源码分析 : Ref (CCObject) 源码分析 cocos2d-x内存管理策略
- int av_packet_ref(AVPacket *dst, const AVPacket *src)源码分析
- boost源码分析之 BOOST_FOREACH
- [osg]源码分析:OSG中的智能指针osg::ref_ptr