std::function | std::bind | lambda
c++ 使用中经常遇到函数对象、函数指针、匿名函数、参数绑定等概念,初次接触总是晕乎乎的,因此本文系统整理下他们的区别、用法。
--1 std::function
泛型函数封装器、用于存储和调用可调用对象。是不是很像函数指针的用途,其实它和函数指针的功能基本一致,只是它能支持lambda 表达式、成员函数的封装和调用,因此通用性更强。
函数指针表达式: 返回类型 (*指针名)(参数类型列表);
std::function 表达式: std::function<返回类型(参数类型列表)>函数名
可以发现,它和lambda 和 std::bind的关系是,lambda 表达式和 std::bind 的返回值可以用std::function 去封装。
#include <iostream>
#include <functional>
int main() {
int value = 42;
auto lambda = [value] { return value; };
// 将 Lambda 表达式封装到 std::function 中
std::function<int()> func = lambda;
// 通过 std::function 调用 Lambda 表达式
int result = func();
std::cout << "Result: " << result << std::endl; // 输出 "Result: 42"
return 0;
}
#include <iostream>
#include <functional>
// 普通函数
void printMessage(const std::string& message, int repeat) {
for (int i = 0; i < repeat; ++i) {
std::cout << message << std::endl;
}
}
int main() {
// 使用 std::bind 绑定参数
auto boundFunction = std::bind(printMessage, "Hello", std::placeholders::_1);
// 将绑定表达式封装到 std::function 中
std::function<void(int)> func = boundFunction;
// 通过 std::function 调用绑定表达式
func(3); // 输出 "Hello" 三次
return 0;
}
--2 std::bind
表达式:std::bind(可调用对象, 参数列表...)
std::bind 是c++ 标准库中的一个函数模板,用于创建一个可调用对象,他可以将一个函数或者可调用对象的参数绑定为固定值(当绑定成员函数的时候,第一个参数可以认为是将该成员函数的this指针绑定为固定值)。
--2.1 绑定普通函数
#include <iostream>
#include <functional>
void print(int a, int b) {
std::cout << a << ", " << b << std::endl;
}
int main() {
auto bound_func = std::bind(print, 10, std::placeholders::_1); // 将第一个参数绑定为 10
bound_func(20); // 输出:10, 20
return 0;
}
--2.2 绑定成员函数
#include <iostream>
#include <functional>
class MyClass {
public:
void print(int a, int b) {
std::cout << a << ", " << b << std::endl;
}
};
int main() {
MyClass obj;
auto bound_member_func = std::bind(&MyClass::print, &obj, std::placeholders::_1, std::placeholders::_2);
bound_member_func(10, 20); // 输出:10, 20
return 0;
}
--2.3 绑定lambda表达式
#include <iostream>
#include <functional>
int main() {
auto lambda = [](int a, int b) {
std::cout << a << ", " << b << std::endl;
};
auto bound_lambda = std::bind(lambda, 10, std::placeholders::_1);
bound_lambda(20); // 输出:10, 20
return 0;
}
--3 lambda
用于在代码中直接定义简短的函数,捕获当前作用域的变量,语法简洁,性能更好。
[capture-list] (parameters) -> return-type { body }
#include <iostream>
#include <functional>
class MyClass {
public:
void printMessage(const std::string& message) {
std::cout << "Message: " << message << std::endl;
}
};
int main() {
MyClass obj;
auto lambda = [&obj](const std::string& message) { obj.printMessage(message); };
lambda("Hello from Lambda!");
return 0;
}
上面的例子有两个疑问?
(1)&obj 是取址吗?那传入的是指针吗?
(2)如果是指针那为什么不是 obj ->printMessage(message); ?
原因是:这里的&代表的捕获引用,而不是取地址,函数体内是obj是外部obj传入的别名对象,不是指针。
这里也可以是[&](const std::string& message) { obj.printMessage(message); }这个写法,代表捕获当前作用域中所有外部变量的引用。