C++ lambda 捕获模式与右值引用的使用

2020-03-22 14:01:11刘景俊

同时,由调用 funce 时的输出可以看到,该输出与 funcb 在移动赋值之前被调用时的输出完全相同。 即移动赋值是将对象整体 move 走了,这与移动构造时的行为不太一样。

std::function 类对象的拷贝构造或者赋值,也需要满足类型匹配原则,如:

std::function<void(int)> funcf = funce;

这行代码会造成编译失败,编译错误信息如下:

../src/DemoTest.cpp: In function ‘intmain()':
../src/DemoTest.cpp:64:36: error: conversion from ‘std::function<void()>' to non-scalar type ‘std::function<void(int)>' requested
   std::function<void(int)> funcf = funce;
                                    ^~~~~
make: *** [src/DemoTest.o] Error 1
src/subdir.mk:18: recipe for target 'src/DemoTest.o' failed

在 lambda 中以值的方式捕获的右值对象,只是在 lambda 的 std::function 对象中做了一份被捕获的右值对象的拷贝,而原来的右值则没有任何改变。

接下来再来看一段示例代码:

#include<iostream>
#include<functional>
#include<string>

using namespace std;

void funcd(std::string&&str){
 printf("String address %p in funcd A, str %sn", &str, str.c_str());
 string strs = std::move(str);
 printf("String address %p in funcd B, str %s, strs %sn", &str, str.c_str(), strs.c_str());
}

void funcc(std::stringstr){
 printf("String address %p in funcc, str %sn", &str, str.c_str());
}

void funcb(std::string&str){
 printf("String address %p in funcb, str %sn", &str, str.c_str());
}

void funca(std::string&&str){
 printf("String address %p in funca A, str %sn", &str, str.c_str());
 std::string stra = str;
 printf("String address %p in funca B, str %s, stra %sn", &str, str.c_str(), stra.c_str());
}

int main(){
 std::string str = "test";
 printf("String address %p in main A, str %sn", &str, str.c_str());

 funca(std::move(str));
 printf("String address %p in main B, str %sn", &str, str.c_str());

// funcb(std::move(str));
 printf("String address %p in main C, str %sn", &str, str.c_str());

 funcc(std::move(str));
 printf("String address %p in main D, str %sn", &str, str.c_str());

 std::string stra = "testa";
 printf("String address %p in main E, stra %sn", &stra, stra.c_str());

 funcd(std::move(stra));
 printf("String address %p in main F, stra %sn", &stra, stra.c_str());

 return 0;
}

上面这段代码在执行时,输出如下:

String address 0x7ffc833f4660 in main A, str test
String address 0x7ffc833f4660 in funca A, str test
String address 0x7ffc833f4660 in funca B, str test, stra test