C++11的std::function源码解析
作者:互联网
C++11的std::function源码解析
1、源码准备
本文是基于gcc-4.9.0的源代码进行分析,std::function是C++11才加入标准的,所以低版本的gcc源码是没有std::function的,建议选择4.9.0或更新的版本去学习,不同版本的gcc源码差异应该不小,但是原理和设计思想的一样的。
源码下载地址:http://ftp.gnu.org/gnu/gcc
2、std::function简介
类模版std::function是一种通用的多态函数包装器。std::function的实例可以对任何可以调用的目标实体进行存储、复制、和调用操作,这些目标实体包括普通函数、Lambda表达式、函数指针、以及其它函数对象等等。std::function对象是对C++中现有的可调用实体的一种类型安全的包裹(我们知道像函数指针这类可调用实体,是类型不安全的)。
通常std::function是一个函数对象类,它包装其它任意的函数对象,被包装的函数对象具有类型为T1, …,TN的N个参数,并且返回一个可转换到R类型的值。std::function使用模板转换构造函数接收被包装的函数对象;特别是,闭包类型可以隐式地转换为std::function。
最简单的理解就是通过std::function对C++中各种可调用实体(普通函数、Lambda表达式、函数指针、以及其它函数对象等)的封装,形成一个新的可调用的std::function对象,让我们不再纠结那么多的可调用实体。
3、源码解析
3.1、std::function解析
std::function
位于libstdc++-v3\include\std\functional
中
template<typename _Res, typename... _ArgTypes>
class function<_Res(_ArgTypes...)> : public _Maybe_unary_or_binary_function<_Res, _ArgTypes...>, private _Function_base
{
typedef _Res _Signature_type(_ArgTypes...);
template<typename _Functor>
using _Invoke = decltype(__callable_functor(std::declval<_Functor&>())(std::declval<_ArgTypes>()...) );
template<typename _Functor>
using _Callable = __check_func_return_type<_Invoke<_Functor>, _Res>;
template<typename _Cond, typename _Tp>
using _Requires = typename enable_if<_Cond::value, _Tp>::type;
public:
typedef _Res result_type;
function() noexcept
:_Function_base()
{
}
function(nullptr_t) noexcept
:_Function_base()
{
}
template<typename _Res, typename... _ArgTypes>
function(const function& __x)
:_Function_base()
{
if (static_cast<bool>(__x))
{
_M_invoker = __x._M_invoker;
_M_manager = __x._M_manager;
__x._M_manager(_M_functor, __x._M_functor, __clone_functor);
}
}
function(function&& __x)
:_Function_base()
{ __x.swap(*this); }
template<typename _Functor, typename = _Requires<_Callable<_Functor>, void>>
function(_Functor __f)
{
typedef _Function_handler<_Signature_type, _Functor> _My_handler;
if (_My_handler::_M_not_empty_function(__f))
{
_My_handler::_M_init_functor(_M_functor, std::move(__f));
_M_invoker = &_My_handler::_M_invoke;
_M_manager = &_My_handler::_M_manager;
}
}
function& operator=(const function& __x)
{
function(__x).swap(*this);
return *this;
}
function& operator=(function&& __x)
{
function(std::move(__x)).swap(*this);
return *this;
}
function& operator=(nullptr_t)
{
if (_M_manager)
{
_M_manager(_M_functor, _M_functor, __destroy_functor);
_M_manager = 0;
_M_invoker = 0;
}
return *this;
}
template<typename _Functor>
_Requires<_Callable<_Functor>, function&> operator=(_Functor&& __f)
{
function(std::forward<_Functor>(__f)).swap(*this);
return *this;
}
template<typename _Functor>
function& operator=(reference_wrapper<_Functor> __f) noexcept
{
function(__f).swap(*this);
return *this;
}
void swap(function& __x)
{
std::swap(_M_functor, __x._M_functor);
std::swap(_M_manager, __x._M_manager);
std::swap(_M_invoker, __x._M_invoker);
}
explicit operator bool() const noexcept
{ return !_M_empty(); }
_Res operator()(_ArgTypes... __args) const;
{
if (_M_empty())
__throw_bad_function_call();
return _M_invoker(_M_functor, std::forward<_ArgTypes>(__args)...);
}
private:
typedef _Res (*_Invoker_type)(const _Any_data&, _ArgTypes...);
_Invoker_type _M_invoker;
从源代码中可以看出以下几点信息:
- 该类是一个可变参模板类
- 该类继承于
_Maybe_unary_or_binary_function
(不分析)和_Function_base
,类成员只有_M_invoker
一个,从定义可以看出这是一个标准的函数指针 - 首先分析
operator()
方法,平时开发中std::function
使用最多的肯定就是重载的括号运算符了,毕竟最终也是要把它当成类似于函数指针的形式来调用的。可以看到operator()
函数里面调用了_M_invoker
函数,并没有什么特殊的处理 - 既然
_M_invoker
能被调用,那就说明它肯定被初始化过了,从调用时传给他的参数来看,多了一个不知道是什么的参数_M_functor
,所以我们可以猜测_M_invoker
并不是直接指向std::function
接管的函数指针的,而是一个类似中间层的东西,在_M_invoker
的实现里面才调用了我们需要执行的那个真实的函数指针 - 只有构造函数
function(_Functor __f)
对_M_invoker
进行了初始化,而使用的就是std::_Function_handler里的方法来初始化_M_invoker
的,std::_Function_handler的实现在后面会讲到 - 还是看构造函数
function(_Functor __f)
,因为std::function
一开始的目的肯定是接管函数指针的,这里的函数指针既可以是普通函数指针也可以是类成员函数指针,甚至是Lambda表达式之类的内容,而我们看到在std::function
这个类里面并没有直接托管函数指针,而是调用了_My_handler::_M_init_functor(_M_functor, std::move(__f))
,推测是由_Function_base
来托管函数指针的
3.2、std::_Function_handler解析
std::_Function_handler
位于libstdc++-v3\include\std\functional
中
template<typename _Res, typename _Functor, typename... _ArgTypes>
class _Function_handler<_Res(_ArgTypes...), _Functor> : public _Function_base::_Base_manager<_Functor>
{
typedef _Function_base::_Base_manager<_Functor> _Base;
public:
static _Res _M_invoke(const _Any_data& __functor, _ArgTypes... __args)
{
return (*_Base::_M_get_pointer(__functor))(std::forward<_ArgTypes>(__args)...);
}
};
template<typename _Functor, typename... _ArgTypes>
class _Function_handler<void(_ArgTypes...), _Functor> : public _Function_base::_Base_manager<_Functor>
{
typedef _Function_base::_Base_manager<_Functor> _Base;
public:
static void _M_invoke(const _Any_data& __functor, _ArgTypes... __args)
{
(*_Base::_M_get_pointer(__functor))(std::forward<_ArgTypes>(__args)...);
}
};
template<typename _Res, typename _Functor, typename... _ArgTypes>
class _Function_handler<_Res(_ArgTypes...), reference_wrapper<_Functor> > : public _Function_base::_Ref_manager<_Functor>
{
typedef _Function_base::_Ref_manager<_Functor> _Base;
public:
static _Res _M_invoke(const _Any_data& __functor, _ArgTypes... __args)
{
return __callable_functor(**_Base::_M_get_pointer(__functor))(std::forward<_ArgTypes>(__args)...);
}
};
template<typename _Functor, typename... _ArgTypes>
class _Function_handler<void(_ArgTypes...), reference_wrapper<_Functor> > : public _Function_base::_Ref_manager<_Functor>
{
typedef _Function_base::_Ref_manager<_Functor> _Base;
public:
static void _M_invoke(const _Any_data& __functor, _ArgTypes... __args)
{
__callable_functor(**_Base::_M_get_pointer(__functor))(std::forward<_ArgTypes>(__args)...);
}
};
template<typename _Class, typename _Member, typename _Res, typename... _ArgTypes>
class _Function_handler<_Res(_ArgTypes...), _Member _Class::*> : public _Function_handler<void(_ArgTypes...), _Member _Class::*>
{
typedef _Function_handler<void(_ArgTypes...), _Member _Class::*> _Base;
public:
static _Res _M_invoke(const _Any_data& __functor, _ArgTypes... __args)
{
return std::mem_fn(_Base::_M_get_pointer(__functor)->__value)(std::forward<_ArgTypes>(__args)...);
}
};
template<typename _Class, typename _Member, typename... _ArgTypes>
class _Function_handler<void(_ArgTypes...), _Member _Class::*> : public _Function_base::_Base_manager<_Simple_type_wrapper< _Member _Class::* > >
{
typedef _Member _Class::* _Functor;
typedef _Simple_type_wrapper<_Functor> _Wrapper;
typedef _Function_base::_Base_manager<_Wrapper> _Base;
public:
static bool _M_manager(_Any_data& __dest, const _Any_data& __source, _Manager_operation __op)
{
switch (__op)
{
#ifdef __GXX_RTTI
case __get_type_info:
__dest._M_access<const type_info*>() = &typeid(_Functor);
break;
#endif
case __get_functor_ptr:
__dest._M_access<_Functor*>() = &_Base::_M_get_pointer(__source)->__value;
break;
default:
_Base::_M_manager(__dest, __source, __op);
}
return false;
}
static void _M_invoke(const _Any_data& __functor, _ArgTypes... __args)
{
std::mem_fn(_Base::_M_get_pointer(__functor)->__value)(std::forward<_ArgTypes>(__args)...);
}
};
从源代码中可以看出以下几点信息:
- 第一个和第二个类继承于
std::_Function_base::_Base_manager
,这两个类是为了处理std::function
接管的是一个普通函数的情况的,它们的区别就是一个处理有返回值的情况,另一个处理没返回值的情况 - 第三个类和第四个类继承于
std::_Function_base::_Ref_manager
,可以看出他是前两个类的偏特化版本,当第二个模板参数为std::reference_wrapper
包装的引用时,就调用这两个偏特化的版本,他们之间的区别也是一个处理有返回值的情况,另一个处理没返回值的情况
因为此时传递的参数是
std::reference_wrapper
对象,我们是不能直接调用这个函数的,因为此时根本不确定这个被包装的函数是一个普通的函数还是类成员函数,如果是类成员函数的话是不能直接使用的,必须调用std::mem_fn
来推断出函数的类型,类中使用的std::__callable_functor
函数也是通过std::mem_fn
实现的。
关于上面提到的std::reference_wrapper
和std::mem_fn
,大家如果可以不懂的话一定要看下面两篇文章,不然的话就像学英语不会英语单词一样,根本不可能看懂std::function
的内容的
- 第五个类和第六个类和前面的差不多,这两个也是特化版本,用于处理第二个模板参数为类成员函数的情况,这里就可以看到直接调用了
std::men_fn
函数了来使得我们可以直接使用类成员函数,从这点也可以看出std::men_fn
函数的重要性,不懂的小伙伴一定要去看前面两篇文章啊。 - 每一个类里面的
_M_invoke
函数都用了_M_get_pointer
(来源不全部相同),从代码逻辑上不难看出_M_get_pointer
函数的作用是从第一个传入参数__functor
中取出一个函数指针(普通函数指针或者类成员函数指针都可以,因为有特化版本,通过std::mem_fn
函数使得类成员函数指针也可以直接调用了),然后将后面的可变参传给这个函数指针,运行它,这个功能是不是就有点似曾相识了,对,这就是我们平时调用函数指针的方法嘛,也就是说std::function
的函数执行功能在这里实现了 - 从代码中我们可以看出这几个类都是和
std::_Function_base
相关的,并且到现在还是不知道_M_functor
究竟是个什么东西,接下来分析std::_Function_base
,看一下里面到底实现了什么功能
3.3、_Any_data解析
_Any_data
位于libstdc++-v3\include\std\functional
中
union _Nocopy_types
{
void* _M_object;
const void* _M_const_object;
void (*_M_function_pointer)();
void (_Undefined_class::*_M_member_pointer)();
};
union _Any_data
{
void* _M_access() { return &_M_pod_data[0]; }
const void* _M_access() const { return &_M_pod_data[0]; }
template<typename _Tp>
_Tp& _M_access()
{ return *static_cast<_Tp*>(_M_access()); }
template<typename _Tp>
const _Tp& _M_access() const
{ return *static_cast<const _Tp*>(_M_access()); }
_Nocopy_types _M_unused;
char _M_pod_data[sizeof(_Nocopy_types)];
};
看std::_Function_base
之前先看一个重要的联合体_Any_data
,这个在前面出现很多次了,但是一直没有介绍一下它究竟是个什么东西,下面简单分析一下:
- 有两个联合体成员,一个是
_M_unused
(没卵用),一个是_M_pod_data
,这两个的占用内存是一样的,具体原因就不讲了,大家可以自己用sizeof
去试一下 - 里面有四个
_M_access
函数,前两个是直接将_M_pod_data
的地址返回出去,不做任何转换,后两个则是可以将_M_pod_data
转换为任意类型返回,从这里可以看出这个_Any_data
的作用就是来接管函数指针的,给我们要接管的函数指针套上一个壳
3.4、std::_Function_base解析
std::_Function_base
的实现位于libstdc++-v3\include\std\functional
中
class _Function_base
{
public:
static const std::size_t _M_max_size = sizeof(_Nocopy_types);
static const std::size_t _M_max_align = __alignof__(_Nocopy_types);
template<typename _Functor>
class _Base_manager
{
protected:
static const bool __stored_locally =
(__is_location_invariant<_Functor>::value
&& sizeof(_Functor) <= _M_max_size
&& __alignof__(_Functor) <= _M_max_align
&& (_M_max_align % __alignof__(_Functor) == 0));
typedef integral_constant<bool, __stored_locally> _Local_storage;
static _Functor* _M_get_pointer(const _Any_data& __source)
{
const _Functor* __ptr = __stored_locally? std::__addressof(__source._M_access<_Functor>()) : __source._M_access<_Functor*>();
return const_cast<_Functor*>(__ptr);
}
static void _M_clone(_Any_data& __dest, const _Any_data& __source, true_type)
{
new (__dest._M_access()) _Functor(__source._M_access<_Functor>());
}
static void _M_clone(_Any_data& __dest, const _Any_data& __source, false_type)
{
__dest._M_access<_Functor*>() = new _Functor(*__source._M_access<_Functor*>());
}
static void _M_destroy(_Any_data& __victim, true_type)
{
__victim._M_access<_Functor>().~_Functor();
}
static void _M_destroy(_Any_data& __victim, false_type)
{
delete __victim._M_access<_Functor*>();
}
public:
static bool _M_manager(_Any_data& __dest, const _Any_data& __source, _Manager_operation __op)
{
switch (__op)
{
case __get_functor_ptr:
__dest._M_access<_Functor*>() = _M_get_pointer(__source);
break;
case __clone_functor:
_M_clone(__dest, __source, _Local_storage());
break;
case __destroy_functor:
_M_destroy(__dest, _Local_storage());
break;
}
return false;
}
static void _M_init_functor(_Any_data& __functor, _Functor&& __f)
{ _M_init_functor(__functor, std::move(__f), _Local_storage()); }
template<typename _Signature>
static bool _M_not_empty_function(const function<_Signature>& __f)
{ return static_cast<bool>(__f); }
template<typename _Tp>
static bool _M_not_empty_function(_Tp* const& __fp)
{ return __fp; }
template<typename _Class, typename _Tp>
static bool _M_not_empty_function(_Tp _Class::* const& __mp)
{ return __mp; }
template<typename _Tp>
static bool _M_not_empty_function(const _Tp&)
{ return true; }
private:
static void _M_init_functor(_Any_data& __functor, _Functor&& __f, true_type)
{ new (__functor._M_access()) _Functor(std::move(__f)); }
static void _M_init_functor(_Any_data& __functor, _Functor&& __f, false_type)
{ __functor._M_access<_Functor*>() = new _Functor(std::move(__f)); }
};
template<typename _Functor>
class _Ref_manager : public _Base_manager<_Functor*>
{
typedef _Function_base::_Base_manager<_Functor*> _Base;
public:
static bool _M_manager(_Any_data& __dest, const _Any_data& __source, _Manager_operation __op)
{
switch (__op)
{
case __get_functor_ptr:
__dest._M_access<_Functor*>() = *_Base::_M_get_pointer(__source);
return is_const<_Functor>::value;
break;
default:
_Base::_M_manager(__dest, __source, __op);
}
return false;
}
static void _M_init_functor(_Any_data& __functor, reference_wrapper<_Functor> __f)
{
_Base::_M_init_functor(__functor, std::__addressof(__f.get()));
}
};
_Function_base() : _M_manager(0) { }
~_Function_base()
{
if (_M_manager)
_M_manager(_M_functor, _M_functor, __destroy_functor);
}
bool _M_empty() const { return !_M_manager; }
typedef bool (*_Manager_type)(_Any_data&, const _Any_data&, _Manager_operation);
_Any_data _M_functor;
_Manager_type _M_manager;
};
从源代码中可以看出以下几点信息:
- 该类有两个类成员,分别是
_M_functor
和_M_manager
,_M_functor
就不用多说了,前面一直有提到它,他的类型_Any_data
也在上一小节讲过了。而_M_manager
则是一个函数指针,有什么用暂时看不出来。 - 这里看一下
_Function_base::_Base_manager
类里面的各个方法
_M_init_functor
函数:该函数前面提到过了,当时看到的是将std::function
接管的函数指针传递给了这个函数,而从前面我们知道_Any_data
类型的数据是可以接管全部类型的函数指针的,所以综合可得_M_init_functor
函数的作用就是将传递给它的第二个参数(函数指针)储存到第一个参数中(_Any_data
类型数据),这样就达成了接管函数指针的功能了_M_get_pointer
函数:这个函数同样在前面被用到了,当时我们只知道通过调用_M_get_pointer
可以获取到我们接管的那个指针,但是不知道是如何实现的,这里可以看出他的实现是非常简单的,也就是从它的传入参数(_Any_data
类型数据)将函数指针取出,并强制类型转换为我们需要的类型而已,里面用到了std::__addressof
,作用就是即使目标变量(类)存在operator&
的重载,也依然能够获得变量的地址。
关于std::__addressof
的详细内容可以看这篇文章《C++11的std::addressof源码解析》_M_manager
函数:该函数就是根据传入的第三个参数来确定执行不同的功能,其余的几个函数无非就是涉及到内存的分配和释放之类的,对我们理解std::function
的影响不大,这里就不展开讲了
- 接下来看一下
_Function_base::_Ref_manager
类
- 可以看到该类继承于
_Function_base::_Base_manager
类,可见他拥有_Function_base::_Base_manager
类实现的所有功能- 该类是处理当
std::function
接管的是一个引用包装类的情况的,为什么这种情况需要单独处理呢?因为如果直接对传入参数取地址,取到的将是引用包装类的地址,而不是我们要接管的函数指针的地址,所以只能搞一个特化版本,就像_Function_base::_Ref_manager
类做的那样,里面的_M_init_functor
函数通过使用reference_wrapper
的get
方法获取到了接管的函数指针的真实地址
_Function_base
类里的其它方法就不讲了,大家自己看一下吧,其余的实现基本都是基于前面讲的那些内容,比较简单
4、总结
本文先是简单介绍了std::function
的用途(对C++中各种可调用实体进行封装),然后通过对源码进行详细分析,我们知道了std::function
是如何实现对可调用实体进行封装的,源码内容会比较复杂,但是其中的设计思路是很值得我们学习借鉴的,尤其是与std::reference_wrapper
和std::mem_fn
配合的那部分代码更是精妙绝伦。
读者如果不清楚std::reference_wrapper
和std::mem_fn
的作用的话,是不可能完全看懂std::function
的源代码的,所以这里再次建议大家先看完下面两篇文章再来学习std::function
相关内容:
最后,如果大家觉得本文写得好的话麻烦点赞收藏一下谢谢,也可以关注该专栏,以后会有更多有用的文章输出的。
标签:11,std,Function,function,functor,manager,源码,__ 来源: https://blog.csdn.net/weixin_43798887/article/details/116571325