Wiki
std::bind
Existing English translations were reused. 4 current source blocks remain in Simplified Chinese, without triggering paid translation.
1.What problem does this section solve?
Sometimes you already have a function, but its parameters and target interface do not match:
- Want to fix certain parameters in advance.
- Want to adjust the order of parameters.
- Want to bind a member function to an object, turning it into an ordinary callback.
std::bind An existing callable object can be adapted into a new callable object.
In modern C++, many bind scenarios can be written more clearly with Lambda. However, std::bind it still frequently appears in legacy projects, ROS2 examples, Boost.Asio callbacks, and member function adaptation, so it is worth mastering.
2.What is this feature?
std::bind 接收一个可调用对象和一组绑定参数,返回一个新的可调用对象。调用新对象时,占位符 _1、_2、_3 表示"调用时传进来的第 1、2、3 个参数"。
std::bind Requires the header file <functional>. The placeholder is in the namespace std::placeholders.
| Syntax | Meaning |
|---|---|
std::bind(f, 10, _1) |
Fixed f The first parameter of 10 |
std::bind(f, _2, _1) |
Swap the order of the two parameters when calling |
std::bind(&C::m, &obj, _1) |
Bind a member function to object obj |
std::bind(f, std::ref(x), _1) |
Bind by reference, not by copy |
3.Example code
3.1.Example 1: Fix some arguments of an ordinary function
#include <functional>
#include <iostream>
#include <string>
void print_student(const std::string& name, int age, int score)
{
std::cout << name << " age=" << age << " score=" << score << "\n";
}
int main()
{
// 程序从 main 函数开始执行,下面的语句会按顺序运行。
using std::placeholders::_1;
using std::placeholders::_2;
print_student("Alice", 20, 95);
// bind 会把函数和部分参数提前绑定成一个可调用对象。
auto print_bob = std::bind(print_student, "Bob", _1, _2);
print_bob(21, 88);
auto print_charlie_score = std::bind(print_student, "Charlie", 22, _1);
print_charlie_score(91);
return 0;
}
Running result:
Alice age=20 score=95
Bob age=21 score=88
Charlie age=22 score=91
3.2.Example 2: Adjusting Parameter Order
The positions of the placeholders determine the order of the arguments received by the original function.
#include <functional>
#include <iostream>
void divide(int a, int b)
{
std::cout << a << " / " << b << " = " << (a / b) << "\n";
}
int main()
{
// 程序从 main 函数开始执行,下面的语句会按顺序运行。
using std::placeholders::_1;
using std::placeholders::_2;
divide(10, 2);
// bind 会把函数和部分参数提前绑定成一个可调用对象。
auto swapped = std::bind(divide, _2, _1);
swapped(2, 10);
auto half = std::bind(divide, _1, 2);
half(10);
half(20);
return 0;
}
Running result:
10 / 2 = 5
10 / 2 = 5
10 / 2 = 5
20 / 2 = 10
3.3.Example 3: Binding Member Functions
A non-static member function requires an object to be called.std::bind The second parameter is usually an object pointer, object reference, or smart pointer.
#include <functional>
#include <iostream>
#include <string>
class Printer
{
std::string prefix_;
public:
explicit Printer(const std::string& prefix) : prefix_(prefix) {}
void print(int id, const std::string& text) const
{
std::cout << prefix_ << " #" << id << ": " << text << "\n";
}
};
int main()
{
// 程序从 main 函数开始执行,下面的语句会按顺序运行。
using std::placeholders::_1;
using std::placeholders::_2;
Printer printer("LOG");
// bind 会把函数和部分参数提前绑定成一个可调用对象。
auto print_any = std::bind(&Printer::print, &printer, _1, _2);
print_any(7, "ready");
auto print_ok = std::bind(&Printer::print, &printer, _1, "ok");
print_ok(8);
return 0;
}
Running result:
LOG #7: ready
LOG #8: ok
Here &printer must remain valid during use of print_any and print_ok. If the bound callback will be stored somewhere longer-lived, smart pointers or more explicit lifetime management usually need to be considered.
3.4.Example 4: Comparison of bind and Lambda
For the same parameter adaptation task, Lambda is often more intuitive because the parameter names and call relationships are clearly written.
#include <functional>
#include <iostream>
int weighted_sum(int base, int x, int y)
{
return base + x * 10 + y;
}
int main()
{
// 程序从 main 函数开始执行,下面的语句会按顺序运行。
using std::placeholders::_1;
using std::placeholders::_2;
// bind 会把函数和部分参数提前绑定成一个可调用对象。
auto by_bind = std::bind(weighted_sum, 100, _1, _2);
auto by_lambda = [](int x, int y) {
return weighted_sum(100, x, y);
};
std::cout << "bind result = " << by_bind(3, 4) << "\n";
std::cout << "lambda result = " << by_lambda(3, 4) << "\n";
auto swapped_bind = std::bind(weighted_sum, 100, _2, _1);
auto swapped_lambda = [](int x, int y) {
return weighted_sum(100, y, x);
};
std::cout << "swapped bind result = " << swapped_bind(3, 4) << "\n";
std::cout << "swapped lambda result = " << swapped_lambda(3, 4) << "\n";
return 0;
}
Running result:
bind result = 134
lambda result = 134
swapped bind result = 143
swapped lambda result = 143
3.5.Example 5: bind copies arguments by default; use std::ref when a reference is needed
std::bind When saving ordinary parameters, they are copied by default. If you want to bind a reference, you must explicitly use std::ref or std::cref.
#include <functional>
#include <iostream>
void add_to(int& total, int value)
{
total += value;
std::cout << "inside total = " << total << "\n";
}
int main()
{
// 程序从 main 函数开始执行,下面的语句会按顺序运行。
int total = 0;
// bind 会把函数和部分参数提前绑定成一个可调用对象。
auto add_copy = std::bind(add_to, total, 5);
add_copy();
std::cout << "outside after copy bind = " << total << "\n";
auto add_ref = std::bind(add_to, std::ref(total), 5);
add_ref();
std::cout << "outside after ref bind = " << total << "\n";
return 0;
}
Running result:
inside total = 5
outside after copy bind = 0
inside total = 5
outside after ref bind = 5
3.6.Example 6: Using this in a member function to bind the current object
前面的示例是在类外部创建对象,再把对象地址 &printer 传给 std::bind。如果 std::bind 本身就在类的成员函数中使用,可以直接传入 this,表示把成员函数绑定到当前对象。
#include <functional>
#include <iostream>
#include <string>
class Robot
{
std::string name_;
public:
explicit Robot(const std::string& name) : name_(name) {}
void on_message(int id, const std::string& text)
{
std::cout << name_ << " #" << id << ": " << text << "\n";
}
void demo()
{
using std::placeholders::_1;
using std::placeholders::_2;
auto callback = std::bind(&Robot::on_message, this, _1, _2);
callback(7, "ready");
callback(8, "running");
}
};
int main()
{
Robot robot("Cyber");
robot.demo();
return 0;
}
Running result:
Cyber #7: ready
Cyber #8: running
The most important thing here is:
auto callback = std::bind(&Robot::on_message, this, _1, _2);
Break it down:
| Parameter | Meaning |
|---|---|
&Robot::on_message |
Member function to be called |
this |
The current object calling this member function |
_1 |
callback() The first parameter passed at call time |
_2 |
callback() The second parameter passed at call time |
A non-static member function cannot be called independently of an object.&Robot::on_message It only specifies "which member function to call"; it must also be told std::bind"on which Robot object to call it."
Outside the class, you can write:
std::bind(&Robot::on_message, &robot, _1, _2);
And within Robot its own member function,this is the pointer to the current object, so you can write directly:
std::bind(&Robot::on_message, this, _1, _2);
For example:
Robot robot("Cyber");
robot.demo();
After entering robot.demo(), the demo() inside this points to robot.
Therefore:
callback(7, "ready");
It can be approximately understood as:
this->on_message(7, "ready");
If the current object is exactly robot, it is equivalent to:
robot.on_message(7, "ready");
Therefore, this type of notation can be remembered as:
std::bind(&类名::成员函数, this, 参数...);
Where the second parameter this serves to:
Tell
std::bind: When this member function is called later, call it on the current object.
This is also a very common way of writing in ROS2 and Boost.Asio, for example:
std::bind(&MyNode::callback, this, _1)
It indicates that MyNode::callback is bound to the current MyNode object, and then the first argument at call time is passed to callback.
Note that this is essentially a pointer. If the bound callback outlives the current object, calling the callback after the object is destroyed may access an already invalid this; therefore, object lifetime must still be considered in asynchronous callbacks.
4.Key syntax explanation
| Syntax | Description | Notes |
|---|---|---|
_1 |
The first parameter passed when calling a new function | From std::placeholders |
_2 |
The second parameter passed when calling a new function | Can be used to adjust the order |
| Fixed value | Written directly in bind parameter |
By default, it is copied and saved |
&Class::method |
Member function pointer | An object still needs to be bound afterward |
this |
The current object pointer inside a member function | Often used as the second parameter when binding a member function |
std::ref(x) |
Bind by reference x |
If not written, std::ref is usually copied |
5.How to choose between bind and Lambda
| Scenario | Recommendation |
|---|---|
| Simple fixed parameters | Lambda or bind both work |
| The parameter relationships need to be read very clearly | Lambda |
| Binding a member function to an old interface | bind is very common, and a Lambda can also be used |
| Requires complex logic, conditional judgment | Lambda |
| Reading old code or ROS2/Boost.Asio examples | Must understand bind |
一句话:新代码优先考虑 Lambda;遇到已有接口适配、旧项目代码、成员函数回调时,要能熟练读懂 std::bind。
6.Common Errors
- Forgot that the placeholder comes from
std::placeholders. - Reversed the order of
_1and_2causing the argument order to be wrong. - Forgot to bind the object when binding a member function.
- After binding an object pointer, the object is destroyed first while the callback is still using it.
- Assumed that
bindstores arguments by reference by default. The default is copy; when a reference is needed, usestd::ref.
7.Usage Recommendations
- In new code, parameter adaptation should first try Lambda.
- When reading ROS2, Boost.Asio, and old project code, you should be able to understand
std::bind(&Class::method, this, _1, _2). - When binding member functions, first consider the object's lifetime.
- When reference semantics are needed, explicitly write
std::reforstd::cref. - Do not write hard-to-read placeholder combinations just to use
bind; clarity is more important than showing off.
8.Summary
std::bind用来固定参数、调整参数顺序、绑定成员函数。_1、_2表示调用新可调用对象时传入的参数位置。- 成员函数中可以把
this作为第二个参数,表示把成员函数绑定到当前对象。 bind默认拷贝绑定参数,需要引用时用std::ref。- 现代 C++ 中很多
bind用法可以用 Lambda 替代。 - 理解
bind对阅读 ROS2、Boost.Asio 和旧 C++ 项目很有帮助。