C++中的bind实践代码 1.std::bind是什么简单来说std::bind是一个函数适配器Adapter。核心作用是“预先固定”一个函数的某些参数从而生成一个新的函数对象。你可以把它想象成一个模具原来的函数需要 3 个原料你先塞进去 1 个固定的原料剩下的 2 个留空占位这就变成了一个只需要 2 个原料的新工具。2. 核心机制占位符 (std::placeholders)要使用std::bind必须先认识它的搭档占位符。它们位于std::placeholders命名空间下通常写成_1,_2,_3..._1代表新函数被调用时的第 1 个参数。_2代表新函数被调用时的第 2 个参数。以此类推。3. 代码实战我们需要包含头文件12#include functionalusingnamespacestd::placeholders;// 方便使用 _1, _2场景 A固定参数减少参数个数假设你有一个减法函数你希望得到一个“减去 10”的专用函数。12345678910111213141516#include iostream#include functionalusingnamespacestd::placeholders;intsub(inta,intb) {returna - b;}intmain() {// 使用 bind// 我们把 sub 的第二个参数 b 固定死为 10// _1 代表新函数 sub_ten 的第一个参数它会被填入 sub 的第一个位置 aauto sub_ten std::bind(sub, _1, 10);// 调用新函数// 实际执行的是 sub(20, 10)std::cout sub_ten(20) std::endl;// 输出 10return0;}场景 B参数重排改变参数顺序std::bind甚至可以颠倒参数的顺序。12345678// 还是上面的 sub(a, b) - a - b// 这次我们交换位置// sub 的第一个参数 (a) 吃新函数的第二个参数 (_2)// sub 的第二个参数 (b) 吃新函数的第一个参数 (_1)auto reverse_sub std::bind(sub, _2, _1);// 调用 reverse_sub(10, 20)// 实际执行 sub(20, 10) - 20 - 10std::cout reverse_sub(10, 20) std::endl;// 输出 10场景 C绑定成员函数最常用的旧式写法这是std::bind在 C11 初期最常见的用途配合std::function做回调特别是为了绑定this指针。123456789101112131415classHero {public:voidheal(intamount) {std::cout Healed amount hp. std::endl;}};intmain() {Hero myHero;// 绑定成员函数// 参数1成员函数指针 Hero::heal// 参数2对象实例的地址 myHero (作为隐式的 this)// 参数3占位符 _1 (将来传进来的 amount)std::functionvoid(int) func std::bind(Hero::heal, myHero, _1);func(50);// 输出: Healed 50 hp.}4. 这里的坑参数拷贝 vs 引用这是std::bind最容易出错的地方。std::bind默认是按值拷贝参数的如果你想绑定的参数是一个引用或者是一个无法拷贝的对象比如unique_ptr你必须显式使用std::ref或std::cref(const ref)。12345678910111213voidupdateScore(int score,intval) {score val;}intmain() {intmyScore 100;// 错误写法// auto update std::bind(updateScore, myScore, _1);// 这会导致 bind 内部拷贝了一份 myScore原本的 myScore 不会变。// 正确写法使用 std::refauto update std::bind(updateScore, std::ref(myScore), _1);update(20);std::cout myScore std::endl;// 输出 120}5. 灵魂拷问为什么现在不推荐用std::bind既然 Lambda 讲完了Bind 也讲完了我们对比一下。现在 C 社区包括官方指南强烈建议能用 Lambda 就别用 Bind。原因如下可读性差bind(func, _2, 10, _1)这种写法像是猜谜语你需要脑补参数填空的对应关系。而 Lambda[](int x, int y) { return func(y, 10, x); }一目了然。容易出错刚才提到的std::ref问题很容易忘记写导致很多隐晦的 Bug。而 Lambda 的捕获列表[]显式且直观。编译器优化Lambda 表达式对编译器来说是透明的代码块容易内联优化。std::bind生成的是复杂的模板对象编译器优化起来比较费劲有时会导致生成的二进制代码更大、更慢。对比示例12345// 任务调用 object.process(data)// 方式 1: std::bind (旧时代)auto task1 std::bind(MyClass::process, object, data);// 方式 2: Lambda (新时代 - 推荐)auto task2 [object, data]() { object.process(data); };到此这篇关于C中的bind代码实践的文章就介绍到这了