本篇将分析c++11引入的 std::function
源码。
TODO:·
分析 std::ref 以及 reference_wrapper 相关部分的源码。
构造函数·
1 | template<typename _Res, typename... _ArgTypes> |
简单几行代码,包含了较多类的概念,下面一点点分析。
_Function_handler
·
这里的关键是_Function_handler
:
1 | // 下面两种重载形式对应 普通函数指针、类实例或者Lambda表达式 , 区别在于是否有返回值 |
每种重载所做的工作都是: 取出实际的调用实体,然后传入参数予以调用
_Any_data
·
1 | union _Any_data |
_M_pod_data
和 _M_unused
占用一样大的空间。从上述的几种_M_access
方法来看,可以直接获取底层存储指针,也可以转换为实际的可调用实体类型指针。
_Nocopy_types
定义如下:
1 | union _Nocopy_types |
_Function_base
·
1 | /// Base class of all polymorphic function object wrappers. |
有两个成员变量: _M_functor
即存储了底层的调用实体。 _M_manager
一个函数指针。
_Function_base::_Base_manager
·
_Function_base
内部还有两个内部类,其中一个为_Base_manager
:
1 | template<typename _Functor> |
这里可以看出:
_Local_storage
类型表示_Functor
的size 是否小于_M_max_size
(即前面_Any_data
的大小), 是否按照_M_max_align
对齐。如果满足,则为true
否则为false
。_M_init_functor
根据_Local_storage
决定将_Functor f
存放于何处。 如果_Local_storage
为true, 则直接存放在(使用placement new)_M_functor
所在的8个字节处(64位平台),否则则直接new
一个heap内存,然后用_M_functor
指向这片内存。_M_get_pointer
根据__stored_locally
决定如何取_Functor
, 如果为true, 直接使用_source
作为可调用实体(这里使用了__addressof
, 其作为是即使_Functor
重载了&
符号,也能取到实际地址,可参考:这里);否则,直接取__source
所指向的内存作为_Functor
指针。
有了如上知识支撑,再看 _Function_handler
的_M_invoke
函数就很简单:
1 | static _Res |
_Function_base::_Ref_manager
·
略,该类是针对 引用包装类 而实现的。
再看构造函数·
1 | template<typename _Res, typename... _ArgTypes> |
operator() 调用·
1 | bool _M_empty() const { return !_M_manager; } |
很简单,调用_M_functor
存储的可调用实体。
总结·
function 源码相对简单,重点关注的有两点:
- 可调用实体
_Functor
的存储方式,直接存在预分配的8字节 or new 一个堆 - ref 相关的调用实现