Lambda表达式里面修改外部变量问题分享!

这是因为, funcb 不能用一个右值引用作为参数来调用。用右值引用作为参数,调用接收左值引用作为参数的函数 funcb 时,会编译失败:

g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF”src/DemoTest.d” -MT”src/DemoTest.o” -o “src/DemoTest.o” “../src/DemoTest.cpp”
../src/DemoTest.cpp: In function ‘int main()’:
../src/DemoTest.cpp:34:18: error: cannot bind non-const lvalue reference of type ‘std::__cxx11::string& {aka std::__cxx11::basic_string<char>&}’ to an rvalue of type ‘std::remove_reference<std::__cxx11::basic_string<char>&>::type {aka std::__cxx11::basic_string<char>}’
   funcb(std::move(str));
         ~~~~~~~~~^~~~~
../src/DemoTest.cpp:17:6: note:   initializing argument 1 of ‘void funcb(std::__cxx11::string&)’
 void funcb(std::string &str) {
      ^~~~~
src/subdir.mk:18: recipe for target ‘src/DemoTest.o’ failed
make: *** [src/DemoTest.o] Error 1

不过,如果 funcb 接收 const 左值引用作为参数,如 void funcb(const std::string &str) ,则在调用该函数时,可以用右值引用作为参数,此时 funcb 的行为与 funca 基本相同。

funcc 函数接收左值作为参数,由 funcc 函数内部及函数调用前后的输出可以看到,由于有了左值作为接收者,传入的右值引用所引用的对象的值被 move 走,进入函数的参数栈对象中了。

funcd 函数与 funca 函数一样,接收右值引用作为参数,但 funcd 的特别之处在于,在函数内部,右值构造了一个新的对象,因而右值引用原来引用的对象的值被 move 走,进入了新构造的对象中。

再来看一段示例代码:

  #include<iostream>  #include<functional>  #include<string>    using namespace std;    void bar(std::string&&str){   printf("String address %p in bar A, str %sn", &str, str.c_str());   string strs = std::move(str);   printf("String address %p in bar B, str %s, strs %sn", &str, str.c_str(), strs.c_str());  }    std::function<void()> bar_bar(std::string &&str) {   auto funf = [&str]() {   printf("String address %p (foo lambda) F, stra %sn", &str, str.c_str());   };   return funf;  }    std::function<void()> foo(std::string &&str) {   printf("String address %p in foo A, str %sn", &str, str.c_str());    // auto funa = [str]() {  // printf("String address %p (foo lambda) A, str %sn", &str, str.c_str());  // bar(str);  // };  // funa();  //  // auto funb = [str]() {  // printf("String address %p (foo lambda) B, str %sn", &str, str.c_str());  // bar(std::move(str));  // };  // funb();    // auto func = [str]() mutable {  // printf("String address %p (foo lambda) C, str %sn", &str, str.c_str());  // bar(str);  // };  // func();     auto fund = [str]() mutable {   printf("String address %p (foo lambda) D, str %sn", &str, str.c_str());   bar(std::move(str));   };   fund();     auto fune = [&str]() {   printf("String address %p (foo lambda) E, str %sn", &str, str.c_str());   bar(std::move(str));   };   fune();     std::string stra = "testa";   return bar_bar(std::move(stra));  }    int main(){   std::string str = "test";   printf("String address %p in main A, str %sn", &str, str.c_str());     auto funcg = foo(std::move(str));   printf("String address %p in main B, str %sn", &str, str.c_str());     funcg();     return 0;  }

上面这段代码的输出如下:

Stringaddress0x7ffc9fe7c5c0 in main A, strtest
Stringaddress0x7ffc9fe7c5c0 in foo A, strtest
Stringaddress0x7ffc9fe7c540 (foo lambda) D, strtest
Stringaddress0x7ffc9fe7c540 in barA, strtest
Stringaddress0x7ffc9fe7c540 in barB,str, strstest
Stringaddress0x7ffc9fe7c5c0 (foo lambda) E, strtest
Stringaddress0x7ffc9fe7c5c0 in barA, strtest
Stringaddress0x7ffc9fe7c5c0 in barB,str, strstest
Stringaddress0x7ffc9fe7c5c0 in main B,str
Stringaddress0x7ffc9fe7c560 (foo lambda) F, stra����

在函数 foo() 中定义的 funa 及对 funa 的调用被注释掉了,这是因为这段代码会导致编译失败,具体的错误信息如下:

Invoking: GCC C++ Compiler
g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF”src/DemoTest.d” -MT”src/DemoTest.o” -o “src/DemoTest.o” “../src/DemoTest.cpp”
../src/DemoTest.cpp: In lambda function:
../src/DemoTest.cpp:25:12: error: cannot bind rvalue reference of type ‘std::__cxx11::string&& {aka std::__cxx11::basic_string<char>&&}’ to lvalue of type ‘const string {aka const std::__cxx11::basic_string<char>}’
     bar(str);
            ^
../src/DemoTest.cpp:7:6: note:   initializing argument 1 of ‘void bar(std::__cxx11::string&&)’
 void bar(std::string &&str) {
      ^~~
src/subdir.mk:18: recipe for target ‘src/DemoTest.o’ failed
make: *** [src/DemoTest.o] Error 1

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/c-cdevelopment/484685.html

(0)
上一篇 2020年11月10日
下一篇 2020年11月10日

精彩推荐