C++ 笔记:std::bind 函数模板详解

张开发
2026/4/4 1:03:20 15 分钟阅读
C++ 笔记:std::bind 函数模板详解
std::bind是 C11 引入的函数适配器定义在functional头文件中核心作用是将函数与参数绑定生成一个可调用对象。它可以延迟函数调用、固定部分参数、修改函数调用形式是 C 中实现函数参数绑定、回调函数封装的核心工具。本文从基础用法、参数绑定、占位符、绑定成员函数、实战场景等维度系统讲解std::bind的使用方法与原理。一、std::bind 基础概念1. 占位符基本用法#include iostream #include functional void show(int a, int b, int c) { std::cout a b c std::endl; } int main() { using namespace std::placeholders; // 简化占位符使用 // _1第一个动态参数_2第二个动态参数 auto func std::bind(show, _1, 100, _2); func(10, 20); // 输出10 100 20 // 调整参数顺序交换 _1 和 _2 auto func_swap std::bind(show, _2, _1, 30); func_swap(10, 20); // 输出20 10 30 return 0; }2. 占位符与固定参数混合本质std::bind是一个模板函数接收一个可调用对象普通函数、函数指针、lambda、成员函数、仿函数和若干参数返回一个新的可调用对象。核心能力固定函数的部分参数参数绑定调整参数的顺序将成员函数转换为普通可调用对象延迟函数执行。头文件使用前必须包含#include functional二、基础用法绑定普通函数1. 无参数绑定直接封装函数直接用bind封装无参函数生成可调用对象调用时执行原函数。#include iostream #include functional // 必须包含 // 普通无参函数 void print() { std::cout Hello std::bind! std::endl; } int main() { // 绑定函数生成可调用对象 func auto func std::bind(print); func(); // 调用输出 Hello std::bind! return 0; }2. 固定参数绑定实参绑定函数时直接传入参数值调用时无需重复传参参数被永久固定。#include iostream #include functional // 带参数的普通函数 int add(int a, int b) { return a b; } int main() { // 绑定 add 函数固定参数 10 和 20 auto add_10_20 std::bind(add, 10, 20); std::cout add_10_20() std::endl; // 输出30 // 固定第一个参数为 5第二个参数后续传入 auto add_5 std::bind(add, 5, std::placeholders::_1); std::cout add_5(15) std::endl; // 输出20515 return 0; }三、占位符std::placeholdersstd::placeholders是std::bind的参数占位符用_1、_2、_3...表示调用时才传入的参数用于保留参数位置调整参数顺序动态传参。#include iostream #include functional void show(int a, int b, int c) { std::cout a b c std::endl; } int main() { using namespace std::placeholders; // 简化占位符使用 // _1第一个动态参数_2第二个动态参数 auto func std::bind(show, _1, 100, _2); func(10, 20); // 输出10 100 20 // 调整参数顺序交换 _1 和 _2 auto func_swap std::bind(show, _2, _1, 30); func_swap(10, 20); // 输出20 10 30 return 0; }_1对应调用时的第一个实参_2对应第二个实参以此类推占位符的数量没有上限根据函数参数个数灵活使用。2. 占位符与固定参数混合绑定函数时可混合使用固定值和占位符灵活控制参数// 函数a - b int sub(int a, int b) { return a - b; } int main() { using namespace std::placeholders; // 固定 b5a 动态传入 auto sub_5 std::bind(sub, _1, 5); std::cout sub_5(20) std::endl; // 20-515 // 固定 a30b 动态传入 auto sub_30 std::bind(sub, 30, _1); std::cout sub_30(10) std::endl; // 30-1020 return 0; }四、进阶用法绑定类成员函数std::bind最常用的场景之一是绑定类的成员函数。注意类成员函数隐含this指针绑定时必须传入对象或对象指针 / 引用作为第一个参数。1. 绑定普通成员函数#include iostream #include functional #include string class Person { private: std::string name; public: Person(std::string n) : name(n) {} // 成员函数 void showInfo(int age) { std::cout 姓名 name 年龄 age std::endl; } }; int main() { using namespace std::placeholders; Person p(张三); // 创建对象 // 绑定成员函数第一个参数是 成员函数第二个参数是对象地址/对象 auto func std::bind(Person::showInfo, p, _1); func(20); // 输出姓名张三年龄20 // 直接传对象会拷贝对象 auto func2 std::bind(Person::showInfo, p, 25); func2(); // 输出姓名张三年龄25 return 0; }2. 绑定静态成员函数静态成员函数无this指针绑定时无需传入对象直接使用类名调用class Test { public: static void staticFunc(int a) { std::cout 静态函数 a std::endl; } }; int main() { auto func std::bind(Test::staticFunc, std::placeholders::_1); func(100); // 输出静态函数100 return 0; }五、绑定仿函数与 lambda 表达式std::bind支持绑定所有可调用对象包括仿函数函数对象和lambda 表达式#include iostream #include functional // 仿函数 struct Multiply { int operator()(int a, int b) { return a * b; } }; int main() { // 1. 绑定仿函数 Multiply mul; auto func1 std::bind(mul, 6, 7); std::cout func1() std::endl; // 42 // 2. 绑定 lambda 表达式 auto lambda [](int a, int b) { return a b; }; auto func2 std::bind(lambda, std::placeholders::_1, 8); std::cout func2(12) std::endl; // 20 return 0; }六、std::bind 与 std::function 配合使用std::function是可调用对象的包装器std::bind生成的可调用对象可以存入std::function实现统一的函数接口管理常用于回调函数、事件处理#include iostream #include functional // 回调函数类型int - int using Callback std::functionint(int); int square(int x) { return x * x; } // 接收回调函数 void process(int num, Callback cb) { std::cout 结果 cb(num) std::endl; } int main() { // 用 bind 封装函数传入 std::function auto func std::bind(square, std::placeholders::_1); process(5, func); // 输出结果25 return 0; }七、注意事项八、总结std::bind是 C 中强大的函数适配器核心价值是灵活绑定函数与参数简化可调用对象的封装与调用。掌握std::bind能大幅提升 C 中函数封装、回调机制的代码灵活性与可读性。总结参数拷贝std::bind绑定参数时默认会拷贝参数值。如果需要传递引用必须使用std::ref引用或std::cref常量引用void setValue(int a) { a 100; } int main() { int x 0; auto func std::bind(setValue, std::ref(x)); // 必须用 ref 传递引用 func(); std::cout x std::endl; // 输出100 return 0; }占位符作用域占位符_1、_2...位于std::placeholders命名空间下建议使用using namespace std::placeholders;简化代码。成员函数绑定必须取地址类名::成员函数且第一个参数必须是对象 / 对象指针。替代方案C11 之后lambda 表达式可以替代大部分std::bind简单场景但bind在绑定成员函数、灵活调整参数顺序时更简洁。基础绑定普通函数固定参数、动态传参核心std::placeholders占位符控制参数位置与顺序std::bind是 C11 函数适配器用于生成可调用对象需包含functional头文件核心用法绑定普通函数 / 成员函数 / 仿函数用_1、_2占位符实现动态传参、调整参数顺序绑定成员函数必须传入对象 / 指针传引用需用std::ref常与std::function配合用于回调函数、参数固定、延迟调用等场景。重点绑定类成员函数必须传入对象 / 指针实战配合std::function实现回调函数、统一接口管理。

更多文章