51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

C++ std::bind 函数适配器

std::bind 是 C++11 引入的一个函数适配器,它可以将函数或可调用对象与其参数绑定在一起,在调用时,减少传入的参数数量,从而简化函数调用。

  1. 使用 {#title-0} ================
#if 1
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<functional>
using namespace std;

void example(int a, int b, int c) { cout << "a=" << a << ", b=" << b << ", c=" << c << endl; }

void test01() { // 绑定时:将 bind 的参数按照顺序绑定到被绑定函数上 // 调用时:第一个位置参数对应 placeholders::_1,第二个位置的参数对应 placeholders::_2 ... 以此类推 // 占位符允许你重新排列参数的顺序 auto func1 = bind(example, placeholders::_2, 100, placeholders::_1); func1(200, 300);

auto func2 = bind(example, 100, placeholders::_1, placeholders::_1);
func2(200, 300);

// 占位符必须从 placeholders::_1 开始 // auto func3 = bind(example, 100, placeholders::_2, placeholders::_3); // func3(200, 300);

}

struct Functor { void operator()(int a, int b) { cout << "a=" << a << ", b=" << b << endl; } };

struct Demo { void sample(int a, int b) { cout << "a=" << a << ", b=" << b << endl; }

static void instance(int a, int b)
{
	cout &lt;&lt; &quot;a=&quot; &lt;&lt; a &lt;&lt; &quot;, b=&quot; &lt;&lt; b &lt;&lt; endl;
}

};

void test02() { // 1. 适配函数对象 auto func1 = bind(Functor(), 100, placeholders::_1); func1(200);

// 2. 适配成员函数
// 2.1 普通成员函数,必须提供对象实例
Demo demo;
auto func2 = bind(&amp;Demo::sample, demo, 100, placeholders::_1);
func2(200);

// 2.2 静态成员函数,不需要提供对象实例 auto func3 = bind(&amp;Demo::instance, 100, placeholders::_1); func3(200);

// 3. 适配匿名函数 auto lambda = [](int a, int b) { cout &lt;&lt; &quot;a=&quot; &lt;&lt; a &lt;&lt; &quot;, b=&quot; &lt;&lt; b &lt;&lt; endl; }; auto func4 = bind(lambda, 100, placeholders::_1); func4(200);

}

int main() { test02(); return EXIT_SUCCESS; } #endif

  1. 探讨 {#title-1} ================

这一小节主要探讨l两个话题。

  • bind 函数返回值
  • bind 绑定参数

示例代码:

#if 1
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<functional>
using namespace std;

void example(int a, int b) { cout << "a=" << a << ", b=" << b << endl; }

// 1. bind 返回类型 void test01() { // _Binder 类型 auto func1 = bind(example, placeholders::_1, 100); cout << typeid(func1).name() << endl; func1(200); // 注意:func1(200, 300, 400) 也是可以,只是忽略后面的参数

// function 类型
function&lt;void(int)&gt; func2 = bind(example, placeholders::_1, 100);
cout &lt;&lt; typeid(func2).name() &lt;&lt; endl;
func2(200);	

// _Binder 保持较轻量的对象封装,直接存储函数和参数的引用或副本,执行时开销较低 // function 提供对可调用对象 _Binder 的又一层封装,提供了更为间接的调用,需要一定的开销

}

// 2. bind 参数拷贝 struct Person { Person() { m_num = 100; cout << "默认构造" << endl; }

Person(const Person&amp;) 
{ 
	cout &lt;&lt; &quot;拷贝构造&quot; &lt;&lt; endl; 
}

Person(Person&amp;&amp;) noexcept { cout &lt;&lt; &quot;移动构造&quot; &lt;&lt; endl; }

int m_num;

};

// 此处修改为引用,如果不希望修改外部对象可以使用 const 引用 void demo(int a, Person& b) { cout << "a=" << a << " b=" << &b << endl; b.m_num = 200; }

void test02() { Person person; // 参数进行绑定时,默认需要拷贝到 bind 函数中 // 使用 ref 引用包装器避免参数传递到 bind 函数时进行拷贝 auto func = bind(demo, placeholders::_1, ref(person)); func(100);

cout &lt;&lt; person.m_num &lt;&lt; endl;

}

int main() { test01(); return EXIT_SUCCESS; } #endif

  1. 思考 {#title-2} ================

C++11 提供了 std::bind 来实现对函数进行参数绑定,以简化函数调用或预设部分参数,但它并不是最理想的解决方案。原因:

  • 语法复杂,代码可读性差。std::bind 需要使用占位符 _1, _2 等来表示参数的位置,这种写法对于简单的函数调用已经显得过于复杂,尤其在参数较多时,可读性下降。
  • 无法捕获局部变量。std::bind 只能绑定传递的参数,而无法捕获作用域内的局部变量。如果想要在绑定时使用上下文中的局部变量,必须额外通过引用或全局变量传递。
  • 性能优势较低。std::bind 实际上会创建一个包含函数指针和参数的复杂函数对象,这些参数存储和解析过程会引入一定的间接调用和运行时解析。

我们可以在大多数的场景下使用 lambda 匿名函数来代替 bind,相对于 bind 函数适配器,lambda 具有更多的优势。

示例代码:

#if 1
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;

void example(int a, int b) { cout << "a=" << a << ", b=" << b << endl; }

struct Functor { void operator()(int a, int b, double c) { cout << "a=" << a << ", b=" << b << ", c=" << c << endl; } };

struct Demo { void sample(int a, int b) { cout << "a=" << a << ", b=" << b << endl; }

static void instance(int a, int b)
{
	cout &lt;&lt; &quot;a=&quot; &lt;&lt; a &lt;&lt; &quot;, b=&quot; &lt;&lt; b &lt;&lt; endl;
}

};

void test() { // 1. 适配普通函数 auto func1 = [](int num) { return example(num, 100); }; func1(200);

// 2. 适配函数对象
auto func2 = [](int num1, int num2) { return Functor()(num1, 100, num2); };;
func2(200, 3.14);

// 2. 适配成员函数 // 2.1 适配普通成员函数,必须提供对象实例 Demo person; auto func3 = [person](int num) mutable { return person.sample(num, 100); }; func3(200);

// 2.2 适配静态成员函数,不需要提供对象实例 auto func4 = [](int num) { return Demo::instance(num, 100); }; func4(200);

}

int main() { test(); return EXIT_SUCCESS; } #endif


赞(4)
未经允许不得转载:工具盒子 » C++ std::bind 函数适配器