包装器 std::function

使用前,包头文件:#include <functional>

std::function 是 C++标准库 中的一个通用函数包装器

它可以储存、复制、调用任何可调用的对象,包括:函数指针成员函数、绑定的成员函数、lambda表达式仿函数等。

1. function 的模板原型
#include <functional>

function<Ret(Args...)> 
// Ret 是被调用函数的返回值类型
// Args... 是被调用函数的形参

举一个函数指针的例子讲解:

int fun(int a, int b) {
    return a + b;
}

int main() {
    function<int(int, int)> func1 = fun; // 此处的 fun 本质是 fun() 的函数指针,与 &fun 无差别
    // <int(, )> : int 为被调用函数的返回值类型
    // (int, int) : 为被调用函数的形参
    
    return 0;
}
2. function 的几种使用方法
2.1 函数指针

上面的例子已经展示过了。

2.2 成员函数
class Plus
{
public:
    static int Plusi(int a, int b) // 静态成员函数
    {
        return a + b;
    }

    double Plusd(double a, double b) // 非静态成员函数
    {
        return a + b;
    }
};

int main()
{
    function<int(int, int)> func2 = &Plus::Plusi;
    cout << func2(1, 1) << endl;
	
    // 非静态成员函数,第一个参数为隐藏的 this 指针
    function<double(Plus, double, double)> func3 = &Plus::Plusd; 
    cout << func3(Plus(), 1.1, 2.2) << endl;

    return 0;
}
2.3 lambda 表达式
int main() 
{
    function<int(int, int)> func4 = [](int a, int b) { return a + b; };
    
    return 0;
}
2.4 仿函数
struct Fun {
    int operator()(int a, int b) {
        return a + b;
    }
};

int main()
{
    function<int(int, int)> func5 = Fun();
    return 0;
}
3. 包装器解决模板效率低下的问题

将下面的代码运行起来,观察 useF() 模板被实例化成了几份?

template<class F, class T>
auto useF(F f, T x) // 实际场景中不建议用 auto 推导返回值类型
{
	static int count = 0;
	cout << "count: " << ++count << endl;
	cout << "count: " << &count << endl;
	return f(x);
}

double f(double x)
{
	return x / 2;
}

struct Fun
{
	double operator()(double x)
	{
		return x / 3;
	}
};

int main()
{
	auto f1 = [](double x) { return x / 4; };
	cout << useF(f1, 11.11) << endl;

	cout << useF(f, 11.11) << endl;
	
	cout << useF(Fun(), 11.11) << endl;
	
	return 0;
}

从运行结果中可以看出, count 始终为 1 且每一个 count 的地址都不相同。事实上,useF() 被实例化成了三份。

我们可以利用包装器解决模板效率低下的问题。

	function<double(double)> func1 = f1;
	cout << useF(func1, 11.11) << endl << endl;

	function<double(double)> func2 = f;
	cout << useF(func2, 11.11) << endl << endl;

	function<double(double)> func3 = Fun();
	cout << useF(func2, 11.11) << endl << endl;

为什么通过 std::function 包装后,useF() 只会实例化出一份呢?

不妨通过 typeid 观察 func1、func2、func3 的类型。

相关推荐

  1. C++进阶--C++11包装

    2024-07-10 09:44:03       33 阅读
  2. C++11:lambda表达式 & 包装

    2024-07-10 09:44:03       18 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-10 09:44:03       4 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-10 09:44:03       5 阅读
  3. 在Django里面运行非项目文件

    2024-07-10 09:44:03       4 阅读
  4. Python语言-面向对象

    2024-07-10 09:44:03       4 阅读

热门阅读

  1. Linux系统管理面试题

    2024-07-10 09:44:03       9 阅读
  2. IO练习网络爬虫获取

    2024-07-10 09:44:03       11 阅读
  3. C++设计模式---备忘录模式

    2024-07-10 09:44:03       6 阅读
  4. WHAT - React useEffect 依赖的 Object.is

    2024-07-10 09:44:03       8 阅读
  5. 探索 Neo4j:图数据库的强大应用

    2024-07-10 09:44:03       9 阅读
  6. Llama-factory源码详细解读

    2024-07-10 09:44:03       10 阅读