lambda 表达式和右值引用是 C++11 的两个非常有用的特性。
lambda 表达式实际上会由编译器创建一个 std::function 对象,以值的方式捕获的变量则会由编译器复制一份,在 std::function 对象中创建一个对应的类型相同的 const 成员变量,如下面的这段代码:
int main(){
std::string str = "test";
printf("String address %p in main, str %sn", &str, str.c_str());
auto funca = [str]() {
printf("String address %p (main lambda), str %sn", &str, str.c_str());
};
std::function<void()> funcb = funca;
std::function<void()> funcc;
funcc = funca;
printf("funcan");
funca();
std::function<void()> funcd = std::move(funca);
printf("funcan");
funca();
printf("funcbn");
funcb();
std::function<void()> funce;
funce = std::move(funcb);
printf("funcbn");
// funcb();
printf("funccn");
funcc();
printf("funcdn");
funcd();
printf("funcen");
funce();
// std::function<void(int)> funcf = funce;
return 0;
}
这段代码的输出如下:
Stringaddress0x7ffd9aaab720 in main, strtest
funca
Stringaddress0x7ffd9aaab740 (main lambda), strtest
funca
Stringaddress0x7ffd9aaab740 (main lambda), str
funcb
Stringaddress0x55bdd2160280 (main lambda), strtest
funcb
funcc
Stringaddress0x55bdd21602b0 (main lambda), strtest
funcd
Stringaddress0x55bdd21602e0 (main lambda), strtest
funce
Stringaddress0x55bdd2160280 (main lambda), strtest
由上面调用 funca 时的输出,可以看到 lambda 表达式以值的方式捕获的对象 str,其地址在 lambda 表达式内部和外部是不同的。
std::function 类对象和普通的魔板类对象一样,可以拷贝构造,如:
std::function<void()> funcb = funca;
由调用 funcb 时的输出,可以看到拷贝构造时是做了逐成员的拷贝构造。
std::function 类对象可以赋值,如:
std::function<void()> funcc; funcc = funca;
由调用 funcc 时的输出,可以看到赋值时是做了逐成员的赋值。
std::function 类对象可以移动构造,如:
std::function<void()> funcd = std::move(funca);
由移动构造之后,调用 funca 和 funcd 时的输出,可以看到移动构造时是做了逐成员的移动构造。
std::function 类对象可以移动赋值,如:
std::function<void()> funce;
funce = std::move(funcb);
printf("funcbn");
// funcb();
这里把移动赋值之后对 funcb 的调用注释掉了,这是因为,作为源的 funcb 在移动赋值之后被调用是,会抛出异常,如:
String address 0x562334c34280 (main lambda), str test funcb terminate called after throwing aninstanceof 'std::bad_function_call' what(): bad_function_call










