C++中的bind实践代码

 更新时间:2025年12月11日 09:20:38   作者:码上睡觉  
std::bind是C++中的一个函数适配器,用于预先固定函数的某些参数,生成一个新的函数对象,它通过占位符来实现参数的占位和重排,本文介绍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. 代码实战

我们需要包含头文件:

#include <functional>
using namespace std::placeholders; // 方便使用 _1, _2

场景 A:固定参数(减少参数个数)

假设你有一个减法函数,你希望得到一个“减去 10”的专用函数。

#include <iostream>
#include <functional>
using namespace std::placeholders;
int sub(int a, int b) {
    return a - b;
}
int main() {
    // 使用 bind:
    // 我们把 sub 的第二个参数 b 固定死为 10
    // _1 代表新函数 sub_ten 的第一个参数,它会被填入 sub 的第一个位置 a
    auto sub_ten = std::bind(sub, _1, 10);
    // 调用新函数:
    // 实际执行的是: sub(20, 10)
    std::cout << sub_ten(20) << std::endl; // 输出 10
    return 0;
}

场景 B:参数重排(改变参数顺序)

std::bind 甚至可以颠倒参数的顺序。

// 还是上面的 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 - 10
std::cout << reverse_sub(10, 20) << std::endl; // 输出 10

场景 C:绑定成员函数(最常用的旧式写法)

这是 std::bind 在 C++11 初期最常见的用途:配合 std::function 做回调,特别是为了绑定 this 指针。

class Hero {
public:
void heal(int amount) {
    std::cout << "Healed " << amount << " hp." << std::endl;
}
};
int main() {
    Hero myHero;
    // 绑定成员函数
    // 参数1:成员函数指针 &Hero::heal
    // 参数2:对象实例的地址 &myHero (作为隐式的 this)
    // 参数3:占位符 _1 (将来传进来的 amount)
    std::function<void(int)> func = std::bind(&Hero::heal, &myHero, _1);
    func(50); // 输出: Healed 50 hp.
}

4. 这里的坑:参数拷贝 vs 引用

这是 std::bind 最容易出错的地方。std::bind 默认是按值拷贝参数的!

如果你想绑定的参数是一个引用,或者是一个无法拷贝的对象

(比如 unique_ptr),你必须显式使用 std::refstd::cref (const ref)。

void updateScore(int& score, int val) {
    score += val;
}
int main() {
    int myScore = 100;
    // 错误写法!
    // auto update = std::bind(updateScore, myScore, _1); 
    // 这会导致 bind 内部拷贝了一份 myScore,原本的 myScore 不会变。
    // 正确写法:使用 std::ref
    auto update = std::bind(updateScore, std::ref(myScore), _1);
    update(20); 
    std::cout << myScore << std::endl; // 输出 120
}

5. 灵魂拷问:为什么现在不推荐用std::bind?

既然 Lambda 讲完了,Bind 也讲完了,我们对比一下。现在 C++ 社区(包括官方指南)强烈建议能用 Lambda 就别用 Bind

原因如下:

  1. 可读性差bind(func, _2, 10, _1) 这种写法像是猜谜语,你需要脑补参数填空的对应关系。而 Lambda [](int x, int y) { return func(y, 10, x); } 一目了然。
  2. 容易出错:刚才提到的 std::ref 问题,很容易忘记写,导致很多隐晦的 Bug。而 Lambda 的捕获列表 [&] 显式且直观。
  3. 编译器优化:Lambda 表达式对编译器来说是透明的代码块,容易内联优化。std::bind 生成的是复杂的模板对象,编译器优化起来比较费劲,有时会导致生成的二进制代码更大、更慢。

对比示例:

// 任务:调用 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代码实践的文章就介绍到这了,更多相关C++ bind内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 深入理解C语言中编译相关的常见错误

    深入理解C语言中编译相关的常见错误

    本篇文章是对C语言中编译相关的常见错误进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • C/C++自主分配出现double free or corruption问题解决

    C/C++自主分配出现double free or corruption问题解决

    这篇文章主要为大家介绍了C/C++出现double free or corruption问题解决,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • 使用mmap实现多进程对大文件拷贝

    使用mmap实现多进程对大文件拷贝

    这篇文章主要介绍了使用mmap实现多进程对大文件拷贝,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-10-10
  • c++ For循环执行顺序流程图解

    c++ For循环执行顺序流程图解

    for 循环允许您编写一个执行特定次数的循环的重复控制结构,这里为大家分享一下具体的执行流程,需要的朋友可以参考下
    2021-10-10
  • C++超详细探究new/delete的使用

    C++超详细探究new/delete的使用

    这篇文章主要介绍了C++中new与deleted关键字的使用,new在动态内存中为对象分配空间并返回一个指向该对象的指针;delete接受一个动态对象的指针, 销毁该对象, 并释放与之关联的内存
    2022-07-07
  • 深入理解c++中virtual关键字

    深入理解c++中virtual关键字

    本篇文章主要是对c++中virtual关键字进行了详细的介绍,需要的朋友可以过来参考下,希望对大家有所帮助
    2014-02-02
  • C++中按引用传递参数的好处有哪些

    C++中按引用传递参数的好处有哪些

    这篇文章主要介绍了C++中按引用传递参数的好处有哪些,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • Qt实现可以计算大数的简单计算器

    Qt实现可以计算大数的简单计算器

    计算器是我们生活中很常见的东西,它可以由多种语言多种方式来实现。本文主要介绍的是基于C++语言,由QT实现的可以计算大数的简单计算器,需要的可以参考一下
    2022-12-12
  • C语言实现无头单向链表的示例代码

    C语言实现无头单向链表的示例代码

    本文主要介绍了C语言实现无头单向链表的示例代码,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • C++实现图像压缩的示例代码

    C++实现图像压缩的示例代码

    这篇文章主要为大家详细介绍了如何使用C++实现图像压缩的功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-12-12

最新评论