C++ | function

文章介绍了C++中的std::function模板类,它是用来封装任何类型的可调用对象,如普通函数、lambda表达式、成员函数等。std::function提供了统一的接口来调用这些不同类型的函数,简化了代码并支持拷贝和移动。文章通过实例展示了如何使用std::function绑定不同类型的函数和成员函数,并讨论了拷贝和移动操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C++ | function

引言

程序设计时,经常需要使用回调函数,如果针对每种不同的可调用对象或函数单独进行声明类型,代码会非常冗余

因此C++ 引入了std::function类模板,std::function对象实例可被拷贝,移动等,可以使用指定的调用特征来直接调用目标元素,不依赖于其元素自身的类型

该函数包装器模板能包装任何类型的可调用实体,如普通函数、函数对象、成员函数、静态函数、lamda表达式和函数对象等。

当std::function对象实例未包含任何实际可调用实体时,调用该std::function对象实例将抛出std::bad_function_call异常。

可调用对象(callable object)包括:

  • 函数
  • 函数指针
  • lambda 表达式
  • bind 创建的对象
  • 重载了函数调用运算符的类(仿函数)

实战

1. 模板类声明

简单说,std::function 就是提前存储了函数实体,在需要的时候回调出来即可。其入参和返回值均与被调用函数保持一致。

如果绑定函数实体的时候,还没确定函数参数,可以通过 std::bind 进行函数入参绑定,等到参数确定好,再传入合适的位置以供调用。

  /** _Res 是返回类型, _ArgTypes 是参数类型
   *  @brief Primary class template for std::function.
   *  @ingroup functors
   *
   *  Polymorphic function wrapper.
   */
  template<typename _Res, typename... _ArgTypes>
    class function<_Res(_ArgTypes...)>
    : public _Maybe_unary_or_binary_function<_Res, _ArgTypes...>,
      private _Function_base
    {
      template<typename _Func,
	       typename _Res2 = __invoke_result<_Func&, _ArgTypes...>>
	struct _Callable
	: __is_invocable_impl<_Res2, _Res>::type
	{ };

      // Used so the return type convertibility checks aren't done when
      // performing overload resolution for copy construction/assignment.
      template<typename _Tp>
	struct _Callable<function, _Tp> : false_type { };

      template<typename _Cond, typename _Tp>
	using _Requires = typename enable_if<_Cond::value, _Tp>::type;

    public:
      typedef _Res result_type;

      // [3.7.2.1] construct/copy/destroy
      function() noexcept
      : _Function_base() { }

      function(nullptr_t) noexcept
      : _Function_base() { }

      function(const function& __x);

      function(function&& __x) noexcept : _Function_base()
      {
	__x.swap(*this);
      }

   // ======================= Randy 还有诸多成员函数 =======================

  
/** 只能和 nullptr 和 0 比较
   *  @brief Compares a polymorphic function object wrapper against 0
   *  (the NULL pointer). 
   *  @returns @c false if the wrapper has no target, @c true otherwise
   *
   *  This function will not throw an %exception.
   */
  template<typename _Res, typename... _Args>
    inline bool
    operator!=(const function<_Res(_Args...)>& __f, nullptr_t) noexcept
    { return static_cast<bool>(__f); }

  /// @overload
  template<typename _Res, typename... _Args>
    inline bool
    operator!=(nullptr_t, const function<_Res(_Args...)>& __f) noexcept
    { return static_cast<bool>(__f); }
          
          
    private:
      using _Invoker_type = _Res (*)(const _Any_data&, _ArgTypes&&...);
      _Invoker_type _M_invoker;
  };

因此,定义一个std::function 的时候,需要将入参及返回值传递给 std::function 模板类即可

std::function<std::string(int)> randy;
std::function<int(char,double)> sesame;

2.普通函数/Lambda表达式/仿函数/类成员函数

#include <iostream>
#include <functional>

// 普通函数
int commonFunc(int lhs, int rhs) {
	return lhs + rhs;
}

// Lambda表达式
auto lamdaFunc = [](int lhs, int rhs) {
	return lhs + rhs;
};

// 函数对象 换成 struct 亦可
class Functor {
public:
	int operator()(int lhs, int rhs) {
		return lhs + rhs;
	}
};


// 类成员函数
class Randy
{
public:
	// 1.类成员函数
	int RandyMemberFunc(int lhs, int rhs) { return lhs + rhs; }
	// 2.类静态成员函数
	static int RandyStaticFunc(int lhs, int rhs) { return lhs + rhs; }
};

int main() {
    // 定义一个 std::function 函数
    std::function<int(int, int)> qcj_CallBack;
    int result = -1;

	// 普通函数
	qcj_CallBack = commonFunc;
	result = qcj_CallBack(2, 1);
	std::cout << "common function: " << result << std::endl;

	// 普通函数指针
	qcj_CallBack = &commonFunc;
	result = qcj_CallBack(2 ,2);
	std::cout << "common function pointer: " << result << std::endl;

	// Lambda表达式
	qcj_CallBack = lamdaFunc;
	result = qcj_CallBack(2, 3);
	std::cout << "lambda function: " << result << std::endl;

	// 函数对象
	Functor functor_randy;
	qcj_CallBack = functor_randy;
	result = qcj_CallBack(2, 4);
	std::cout << "function object: " << result << std::endl;

	// 类成员函数(使用std::bind绑定类成员函数, std::placeholders::_2为占位符,顺序与原函数入参对应,次序可调换)
             // qcj_CallBack = std::bind(&Randy::RandyMemberFunc, randy, std::placeholders::_2, std::placeholders::_1);
            // 上式这么写也可以,调用时 第2个入参在前,第1个入参在后
	Randy randy;
	qcj_CallBack = std::bind(&Randy::RandyMemberFunc, randy, std::placeholders::_1, std::placeholders::_2);
	result = qcj_CallBack(2, 5);
	std::cout << "class member function: " << result << std::endl;

	// 类静态成员函数
	qcj_CallBack = Randy::RandyStaticFunc;
	result = qcj_CallBack(2, 6);
	std::cout << "class static member function: " << result << std::endl;

	return 0;
}

结果:

common function: 3
common function pointer: 4
lambda function: 5
function object:: 6
class member function: 7
class static member function: 8

3.函数指针/模板函数/模板函数对象

#include <iostream>
#include <functional>

// 回调函数
std::function<std::string(std::string)> RandyFuncCallBack;

// 函数指针
std::string (*RandyFuncPtr)(std::string);

template<typename T>
T RandyTemplate(T t_arg){
    return "三戒纪元: " + t_arg;
}

// 模板函数对象
template <typename T>
struct RandyStruct{
    T operator()(T t_arg){
        return "Randy struct: " + t_arg;
    }
};

int main(int argc, char *argv[]){
    //std::function包装模板函数
    RandyFuncCallBack = RandyTemplate<std::string>; 
    std::cout << RandyFuncCallBack("std::function called.") << std::endl; 
    
    // 函数指针
    RandyFuncPtr = RandyTemplate;
    RandyFuncCallBack = RandyFuncPtr;
    std::cout << RandyFuncCallBack("function ptr called.") << std::endl;
    
    // 模板函数对象
     RandyFuncCallBack = RandyStruct<std::string>(); 
    std::cout << RandyFuncCallBack("struct function called.") << std::endl;
    return 0;
}

结果:

三戒纪元: std::function called.
三戒纪元: function ptr called.
Randy struct: struct function called.

4.静态函数/类模板静态函数/模板类成员函数/类成员函数

#include <iostream>
#include <functional>

// 回调函数
std::function<std::string(std::string)> RandyFuncCallBack;

// 类成员函数
struct Randy{
    std::string RandyCommonFunc(std::string sesame){
        return "Randy common function: " + sesame;
    }

    static std::string RandyStaticFunc(std::string t_arg){
        return "Randy static function: " + t_arg;
    }
};

// 模板类
template <typename T>
struct RandyTemplateStruct{
    // 模板对象函数
    T RandyTemplateFunc(T sesame){
        return "Randy Template function: " + sesame;
    }

    // 模板对象静态函数
    static T RandyTemplateStaticFunc(T t_arg){
        return "Randy Template static function: " + t_arg;
    }
};

int main(int argc, char *argv[]){
    Randy randy;

    // 类成员函数
    RandyFuncCallBack = std::bind(&Randy::RandyCommonFunc, &randy, std::placeholders::_1); 
    std::cout << RandyFuncCallBack("RandyCommonFunc called.") << std::endl; 

    // 类成员函数
    RandyFuncCallBack = randy.RandyStaticFunc;
    std::cout << RandyFuncCallBack("RandyStaticFunc called.") << std::endl; 

    // 模板对象函数
    RandyTemplateStruct<std::string> randyTemplate;
    RandyFuncCallBack = std::bind(&RandyTemplateStruct<std::string>::RandyTemplateFunc, &randyTemplate, std::placeholders::_1); 
    std::cout << RandyFuncCallBack("RandyTemplateFunc called.") << std::endl; 

    // 模板对象静态函数
    RandyFuncCallBack = RandyTemplateStruct<std::string>::RandyTemplateStaticFunc;
    std::cout << RandyFuncCallBack("RandyTemplateStaticFunc called.") << std::endl; 
    return 0;
}

结果:

Randy common function: RandyCommonFunc called.
Randy static function: RandyStaticFunc called.
Randy Template function: RandyTemplateFunc called.
Randy Template static function: RandyTemplateStaticFunc called.

5. copy/move

#include <iostream>
#include <functional>

// 回调函数
std::function<std::string(std::string)> RandyFuncCallBack;

std::string PrintRandy(std::string sesame) {
	return ">>>>>>>>>> 三戒纪元: " + sesame + " <<<<<<<<<<";
}


int main(int argc, char *argv[]){
    // 未包装任何对象实体
    std::cout << RandyFuncCallBack("RandyFuncCallBack") << std::endl;
    // 结果为:Aborted (core dumped)
    
    RandyFuncCallBack = PrintRandy;
    std::cout << RandyFuncCallBack("RandyFuncCallBack") << std::endl;

     //拷贝
    std::function<std::string(std::string)> CallBack_Copy(RandyFuncCallBack);
    std::cout << CallBack_Copy("CallBack_Copy") << std::endl;
    
    //拷贝赋值运算符
    std::function<std::string(std::string)> CallBack_CopyAssign = RandyFuncCallBack; 
    std::cout << CallBack_CopyAssign("CallBack_CopyAssign.") << std::endl;

    //移动赋值运算符
    std::function<std::string(std::string)>&& CallBack_MoveAssign = std::move(RandyFuncCallBack); 
    std::cout << CallBack_MoveAssign("CallBack_MoveAssign") << std::endl;
    std::cout << RandyFuncCallBack("RandyFuncCallBack") << std::endl;

    return 0;
}

结果:

>>>>>>>>>> 三戒纪元: RandyFuncCallBack <<<<<<<<<<
>>>>>>>>>> 三戒纪元: CallBack_Copy <<<<<<<<<<
>>>>>>>>>> 三戒纪元: CallBack_CopyAssign. <<<<<<<<<<
>>>>>>>>>> 三戒纪元: CallBack_MoveAssign <<<<<<<<<<
>>>>>>>>>> 三戒纪元: RandyFuncCallBack <<<<<<<<<<

Reference


欢迎关注公众号【三戒纪元】

<think>好的,用户想了解C++11中std::function的用法和特性。我需要先回忆一下std::function的基本概念,它是用来存储可调用对象的通用函数包装器,可以处理函数指针、lambda表达式、绑定表达式等。 首先,我应该解释std::function的作用,然后说明它的基本语法,比如模板参数中的返回类型和参数类型。接着,举例说明如何声明不同类型的std::function对象,比如无参函数、带参数的函数、成员函数等。 然后,需要提到std::function的初始化方式,可以通过赋值或者构造函数来绑定不同的可调用对象。这里可能需要举几个例子,比如使用lambda表达式、函数对象或者bind表达式。 还要注意提到std::function的大小和性能特点,比如它可能有一定的类型擦除开销,但提供了灵活性。此外,结合C++11的其他特性,比如auto关键字和lambda,展示如何简化代码。 用户可能还关心std::function与函数指针的区别,以及在实际应用中的使用场景,比如回调机制、策略模式等。需要确保例子清晰,代码正确,符合C++11标准。 另外,根据提供的引用,用户之前可能对线程池和性能优化有兴趣,可以提到std::function在线程池任务调度中的应用,比如将任务封装成std::function传递给线程池处理,避免频繁创建线程,如引用[4]所述。 最后,生成相关问题时要覆盖std::function的特性、与其他组件的对比、性能考虑以及实际应用场景,确保问题有针对性,帮助用户深入理解。</think>### C++11 std::function 用法与特性详解 #### 一、核心概念 $std::function$ 是C++11引入的通用函数包装器(类型擦除容器),可存储任何*可调用对象*(callable object),包括: - 普通函数指针 - 类成员函数指针 - lambda表达式 - 函数对象(重载了operator()的类) - bind表达式结果 #### 二、基本语法 $$std::function<ReturnType(ArgTypes...)> varName;$$ 示例: ```cpp std::function<void()> func1; // 无参数无返回值 std::function<int(int, int)> func2; // 带两个int参数返回int std::function<double(double)> func3; // 数学函数包装器 ``` #### 三、特性与用法 1. **多态绑定** ```cpp // 绑定普通函数 int add(int a, int b) { return a + b; } std::function<int(int,int)> f_add = add; // 绑定lambda表达式 auto lambda = [](int x) { return x*x; }; std::function<int(int)> f_square = lambda; // 绑定类成员函数 struct Calculator { int multiply(int a, int b) { return a*b; } }; Calculator cal; using namespace std::placeholders; std::function<int(int,int)> f_mul = std::bind(&Calculator::multiply, &cal, _1, _2); ``` 2. **空状态检测** ```cpp if(f_add) { // 检查是否已绑定有效对象 std::cout << f_add(2,3); // 输出5 } ``` 3. **与lambda配合使用**(引用示例[3]的典型用法) ```cpp std::function<int(int)> lfib = [&lfib](int n) { return n < 2 ? 1 : (n + lfib(n-1)); }; std::cout << lfib(10); // 输出55 ``` 4. **类型擦除代价** - 比直接调用函数指针多1次间接调用 - 存储空间通常是普通指针的2-3倍 - 适合需要动态绑定的场景,高频调用建议直接使用模板 #### 四、应用场景 1. **回调机制** ```cpp class Button { std::function<void()> onClick; public: void setCallback(std::function<void()> cb) { onClick = cb; } void click() { if(onClick) onClick(); } }; ``` 2. **策略模式实现** ```cpp class Sorter { std::function<bool(int,int)> compare; public: void setStrategy(std::function<bool(int,int)> cmp) { compare = cmp; } void sort(int* arr, int n) { // 使用compare进行排序... } }; ``` 3. **线程池任务封装**(参考引用[4]的线程池应用) ```cpp class ThreadPool { public: void addTask(std::function<void()> task) { // 将任务加入队列 } }; ``` #### 五、性能优化建议 1. 优先使用auto+lambda的组合 2. 对固定签名的回调使用模板参数 3. 高频调用场景避免多层function嵌套 4. 使用std::ref包装大型函数对象
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值