Wiki
std::function
Existing English translations were reused. 1 current source blocks remain in Simplified Chinese, without triggering paid translation.
1.What problem does this section solve?
Ordinary functions, function pointers, lambdas, and function objects can all be "called," and they are collectively referred to as callable objects. However, their concrete types are not the same:
- A regular function has a function type.
- A function pointer is a pointer type.
- Each lambda has a distinct compiler-generated type.
- A function object is a user-defined class type.
If you only call it once immediately, differing types are usually not a problem; but if you want to store the callback in a member variable, or put multiple different callbacks into the same container, you need a unified type.
std::function It is the general-purpose callable object wrapper provided by the standard library.
2.What is this feature?
std::function<返回值(参数列表)> Any callable object matching the signature can be saved.
For example, std::function<int(int, int)> means: save one that can be called with two int and returns int callable object.
3.C++ Standard Edition
std::function Provided starting from C++11, requires the header file <functional>.
4.Common scenarios
| Scenario | Is it suitable?std::function |
Reason |
|---|---|---|
| Calling a callback once immediately inside a function | Not necessarily | Template parameters are usually more lightweight |
| Storing a callback in a class member variable | Suitable | Member variables need a stable type |
vectorStoring multiple different lambdas |
Suitable | Container elements must all be of the same type |
| A small function in a high-frequency performance hotspot | Be cautious | std::functionThere is type erasure overhead |
| Storing only captureless functions | A function pointer also works | But a function pointer cannot store a capturing lambda |
5.Example code
5.1.Example 1: Uniformly storing callable objects of different types
#include <functional>
#include <iostream>
int add(int a, int b)
{
return a + b;
}
struct Multiply
{
int operator()(int a, int b) const
{
return a * b;
}
};
int main()
{
// 程序从 main 函数开始执行,下面的语句会按顺序运行。
// std::function 可以保存普通函数、lambda 或函数对象。
std::function<int(int, int)> op;
op = add;
std::cout << "add: " << op(3, 4) << "\n";
int (*function_pointer)(int, int) = add;
op = function_pointer;
std::cout << "function pointer: " << op(5, 6) << "\n";
op = [](int a, int b) {
return a - b;
};
std::cout << "lambda: " << op(10, 3) << "\n";
op = Multiply{};
std::cout << "function object: " << op(7, 8) << "\n";
return 0;
}
Running result:
add: 7
function pointer: 11
lambda: 7
function object: 56
5.2.Example 2: Passing a callback as a std::function parameter
In this example,calculate does not care whether what is passed in is an ordinary function or a lambda; it only requires the signature to be int(int, int).
#include <functional>
#include <iostream>
int add(int a, int b)
{
return a + b;
}
// std::function 可以保存普通函数、lambda 或函数对象。
int calculate(int a, int b, const std::function<int(int, int)>& op)
{
return op(a, b);
}
int main()
{
// 程序从 main 函数开始执行,下面的语句会按顺序运行。
int x = 10;
int y = 5;
int r1 = calculate(x, y, add);
std::cout << "add result = " << r1 << "\n";
int r2 = calculate(x, y, [](int a, int b) {
return a * b;
});
std::cout << "multiply result = " << r2 << "\n";
int offset = 100;
int r3 = calculate(x, y, [offset](int a, int b) {
return a + b + offset;
});
std::cout << "with offset result = " << r3 << "\n";
return 0;
}
Running result:
add result = 15
multiply result = 50
with offset result = 115
5.3.Example 3: Save the callback to a class member variable
A function pointer cannot store a lambda with captures;std::function it can, so it is very suitable for storing event callbacks.
#include <functional>
#include <iostream>
#include <string>
#include <utility>
class Button
{
// std::function 可以保存普通函数、lambda 或函数对象。
std::function<void()> on_click_;
public:
void set_on_click(std::function<void()> callback)
{
on_click_ = std::move(callback);
}
void click() const
{
if (on_click_)
{
on_click_();
}
else
{
std::cout << "no callback\n";
}
}
};
int main()
{
// 程序从 main 函数开始执行,下面的语句会按顺序运行。
Button button;
button.click();
std::string name = "Save";
int count = 0;
button.set_on_click([name, &count]() {
++count;
std::cout << name << " clicked, count = " << count << "\n";
});
button.click();
button.click();
return 0;
}
Running result:
no callback
Save clicked, count = 1
Save clicked, count = 2
Here capture by value name and capture by reference count. Since both button and count are in main and count lives longer than the callback invocation, this example is safe. In real asynchronous scenarios, lifecycle handling must be more careful when storing callbacks.
5.4.Example 4: Put multiple different callbacks into the same container
Each Lambda has a different type and cannot be placed directly into the same vector. After using std::function<void()> they then have a unified type.
#include <functional>
#include <iostream>
#include <string>
#include <vector>
int main()
{
// 程序从 main 函数开始执行,下面的语句会按顺序运行。
// std::function 可以保存普通函数、lambda 或函数对象。
// vector 是动态数组,元素数量可以在运行时变化。
std::vector<std::function<void()>> tasks;
int total = 0;
std::string label = "task";
tasks.push_back([label]() {
std::cout << label << " A\n";
});
tasks.push_back([&total]() {
total += 10;
std::cout << "add 10, total = " << total << "\n";
});
tasks.push_back([&total]() {
total *= 2;
std::cout << "double, total = " << total << "\n";
});
for (const auto& task : tasks)
{
task();
}
std::cout << "final total = " << total << "\n";
return 0;
}
Running result:
task A
add 10, total = 10
double, total = 20
final total = 20
5.5.Example 5: Template parameters can also accept callbacks when invoked only immediately
std::functionThe advantage is "saving and unifying types." If it is only called immediately and does not need to be saved, function templates are usually more lightweight.
#include <iostream>
template<typename Callback>
void repeat(int times, Callback callback)
{
for (int i = 0; i < times; ++i)
{
callback(i);
}
}
int main()
{
// 程序从 main 函数开始执行,下面的语句会按顺序运行。
repeat(3, [](int i) {
std::cout << "i = " << i << "\n";
});
// 返回 0 表示程序正常结束。
return 0;
}
Running result:
i = 0
i = 1
i = 2
6.Key syntax explanation
| 写法 | 含义 | 注意事项 |
|---|---|---|
std::function<void()> |
保存无参数、无返回值的回调 | 常用于按钮、定时器、任务队列 |
std::function<int(int, int)> |
保存两个 int 参数、返回 int 的可调用对象 |
签名必须匹配 |
if (callback) |
判断 std::function 是否为空 |
空回调不能直接调用 |
std::move(callback) |
把传入的回调移动到成员变量 | 避免不必要拷贝 |
vector<std::function<void()>> |
保存多个不同类型的回调 | 容器元素类型统一 |
7.The relationship between std::function and Lambda
Lambda is a callable object,std::function is a wrapper used to hold a callable object. They are not mutually substitutable.
| Requirement | Recommendation |
|---|---|
| Write a short logic inline | Lambda |
| Store the callback as a variable or member | std::function |
| Put multiple different lambdas into a container | std::function |
| Called once and performance-sensitive | Function template |
8.Common Errors
- Empty
std::functionDirect call. Before calling, first checkif (callback). - Signature mismatch. For example, the callback requires
int(int, int),so you cannot pass a callable object that accepts only one parameter. - When saving the callback, the reference captured a local variable that has already been destroyed.
- Even if it only needs to be called temporarily once, also write the parameter as
std::function,which incurs unnecessary overhead in performance-sensitive code. - Assuming that a member function can be directly assigned to
std::function<void(int)>. A non-static member function also requires an object; the next section will usestd::bindand Lambda to solve this problem.
9.Usage Recommendations
- When you need to store a callback, use
std::function. - When you need to unify callbacks of different types, use
std::function. - When you only need to invoke a callback once immediately, prefer a template parameter.
- When storing callbacks, pay special attention to the lifetime of captured objects.
- Do not treat
std::functionas the sole answer for all callback scenarios; it is a tool for clarity and flexibility, and it also has a certain runtime overhead.
10.Summary
- Callable objects include ordinary functions, function pointers, lambdas, function objects, etc.
std::function<返回值(参数...)>Use a uniform type to store callable objects with matching signatures.std::functionSuitable for storing callbacks, serving as member variables, and placing into containers.- An empty
std::functioncannot be called. - For callbacks that are only invoked temporarily once, template parameters are usually more lightweight.