C++ std::bind的作用和用法

一句话概括

std::bind 接收一个可调用对象和一组实参,返回一个新的可调用对象,用来固定部分参数 或调整参数顺序与数量 。头文件 <functional>,C++11 起提供。

最常用的两种用法

固定部分参数

cpp 复制代码
#include <functional>

int add(int a, int b);

using namespace std::placeholders;
auto add10 = std::bind(add, 10, _1);  // _1 = 新对象的第 1 个参数
add10(5);                             // 15

占位符 _1, _2, ... 标记"调用时再填"的位置,其余实参按值拷贝进返回对象。

调整参数顺序

cpp 复制代码
auto swapped = std::bind(add, _2, _1);
swapped(3, 4);  // add(4, 3) == 7

返回对象遵循 INVOKE 语义,可直接交给 std::function、std::thread 或标准算法。

绑定类成员

成员函数

cpp 复制代码
struct Widget {
    void draw(int layer);
};

Widget w;
auto d1 = std::bind(&Widget::draw, &w, _1);           // 传对象指针
auto d2 = std::bind(&Widget::draw, std::ref(w), _1);  // 传引用,不拷贝对象

成员函数隐含 this,所以第一个实参必须传对象:指针最常用,不想拷贝对象就用 std::ref。

成员变量

std::bind 同样接受成员变量指针,调用时返回该成员的引用,读、写都行:

cpp 复制代码
struct Widget {
    int value = 0;
};

Widget w;
auto value = std::bind(&Widget::value, &w);
value();       // 读:0
value() = 42;  // 写:w.value == 42

auto get = std::bind(&Widget::value, _1);  // 对象留到调用时再传
get(&w);                                   // 42

要点:

  • 绑定时必须给出对象(指针或 std::ref);对象为 const 时得到 const 引用,写入会编译失败。
  • 返回的是成员引用,不延长对象生命周期,对象销毁后再调用即悬垂。
  • 典型用途是泛型代码把"取成员"当可调用对象,例如按成员排序:
    std::bind(&Widget::value, _1) < std::bind(&Widget::value, _2)。
  • 日常代码里 lambda 更直观:[&w] { return w.value; }。

bind 的短板:占位符数量有上限、需引入 std::placeholders;重载函数不能直接传入,须先转成函数指针;只能按位置绑定,参数个数或顺序写错时编译信息不友好。

常见坑

  • 多余的实参被静默丢弃 :add10(5, 99) 合法,99 直接忽略;实参不足则编译失败。
  • 忘记 std::ref:修改的是 bind 内部保存的副本。
  • 重载函数名歧义 :std::bind(f, ...) 无法推导,需写成 std::bind(static_cast<int(*)(int)>(f), _1)。

结语

std::bind 是 C++11 的参数适配器:固定参数、重排顺序、绑定成员,一行完成。但表达力和可读性都不如 lambda,现代代码应优先 lambda。

相关推荐
流浪0012 小时前
计算机网络篇8:传输层——序列化与反序列化,TCP 面向字节流的报文边界由应用层自己切
网络协议·tcp/ip·计算机网络·1024程序员节·序列化反序列化·面向字节流·面向数据包
职豚求职小程序刷题2 小时前
中国旅游集团27校招在线测评攻略(附练习题库)
1024程序员节
淡淡的香烟2 小时前
Flutter实现多语言切换
android·flutter·1024程序员节
DogDaoDao2 小时前
数字信号处理:数字域(时域)与频域的关系与作用——从傅里叶变换到 FFT 的完整推演
数字信号处理·1024程序员节·傅里叶变换·卷积·dct变换·时域·频域
Percep_gan2 小时前
调用天翼云的对象存储ZOS,很详细
java·1024程序员节
JulyLi20192 小时前
yolo检测适配昇腾Atlas300IDuo笔记
yolo·1024程序员节
遇雪长安2 小时前
MCU 固件启动即崩,bootloader 如何发现
1024程序员节
Zevalin爱灰灰2 小时前
Linux入门第一部分(Ubuntu入门篇) 第二章 浅尝Ubuntu(二)
linux·嵌入式·1024程序员节
泡海椒2 小时前
JQuick-SQL REST API 数据接入:应用层调用接口后注册分析表
数据库·sql·1024程序员节