std::function
是一个类型擦除对象。这意味着它擦除了某些操作的详细细节,并为它们提供了一个统一的运行时接口。对于 std::function
,主要的操作包括复制/移动、销毁,以及通过 operator()
(即“类似函数的调用运算符”)进行 ‘调用’。详细的文档
用更简洁的英语来说,这意味着 std::function
可以包含几乎任何像函数指针一样调用的对象。
它所支持的签名位于尖括号内:std::function
表示不带参数并返回 void
的函数。std::function
表示带有两个 int
参数并返回 double
的函数。通常,std::function
支持存储任何类似函数的对象,其参数可以从其参数列表进行转换,其返回值可以转换为其返回值。
重要的是要知道,std::function
和 Lambda 是不同的东西,尽管它们可能是兼容的。
接下来的代码是一个 Lambda 表达式。这是 C++11 中的新语法,用于编写类似函数的简单对象,即可以用 ()
调用的对象。这些对象可以进行类型擦除并存储在 std::function
中,但会带来一些运行时开销。
如何判定两个std::function 对象是否相等?可以看一个demo
auto callback1 = []() {std::cout << "Device Change1!\n"; };
auto callback2 = []() {std::cout << "Device Change2!\n"; };
auto callback3 = []() {std::cout << "Device Change3!\n"; };
std::function<void()> func1 = callback1;
std::function<void()> func2 = callback2;
std::function<void()> func3 = callback3;
std::cout << "callback1 target_type: " << func1.target_type().name() << std::endl;
std::cout << "callback2 target_type: " << func2.target_type().name() << std::endl;
std::cout << "callback3 target_type: " << func3.target_type().name() << std::endl;
std::cout << "callback3 == callback2: " << int(callback2 == callback3) << std::endl;
输出:
callback1 target_type: class
callback2 target_type: class
callback3 target_type: class
callback3 == callback2: 0
所以std::function 并没有实现 ==, 可以通过 target_type 来对比每个 std::function 的类型。这种方式是不是只适合于Lambda表达式呢?再验证一下。
void fnCallback1() {
std::cout << "callback1 \n";
}
void fnCallback2() {
std::cout << "callback2 \n";
}
std::function<void()> func1 = fnCallback1;
std::function<void()> func2 = fnCallback2;
std::cout << "callback1 target_type: " << func1.target_type().name() << std::endl;
std::cout << "callback2 target_type: " << func2.target_type().name() << std::endl;
std::cout << "callback3 == callback2: " << int(fnCallback1 == fnCallback2) << std::endl;
[](){ code }
特别是一个非常简单的 Lambda。它对应于以下形式:
struct some_anonymous_type {
some_anonymous_type() {}
void operator()const{
code
}
};
所以Lambda 表达式就是重载了 () 的操作符吗?
Lambda 的一般形式
[ capture_list ]( argument_list )
-> return_type optional_mutable
{
code
}
更加一般的内部形式
struct some_anonymous_type {
// capture_list turned into member variables
some_anonymous_type( /* capture_list turned into arguments */ ):
/* member variables initialized */
{}
return_type operator()( argument_list ) const {
code
}
};