Moving with lambdas

后端 未结 1 1244
轻奢々
轻奢々 2021-02-19 02:06

When using lambda functions, let\'s say that you decide to copy a variable (with the [=] notation). If you never reference that variable again, is the compiler allowed to move i

1条回答
  •  眼角桃花
    2021-02-19 02:45

    If you never reference that variable again, is the compiler allowed to move it into the resultant function object?

    No. The only situation where the compiler is allowed to replace a copy with a move are the exact same situations where it is allowed to perform a copy elision. These situations include returning a local object by value or initializing an object with a temporary. In these cases the compiler is allowed to elide the copy by making source and target the same object. If the compiler is not able to do that for whatever reason it has to consider the source object as an rvalue with respect to overload resolution for selecting the appropriate constructor for the target object. In your case, however, file is an Lvalue and none of the cases from above apply. You would have to use an explicit move.

    Unfortunately, C++11 doesn't have a syntax for a "move capture". IMHO, it's a shame. But std::bind supports this. It should be possible to combine std::bind with a lambda expression like this:

    void foo(char const* p) {
       string s = p;
       auto fun = bind([](string const& s){
          ...
       },move(s));
       fun();
    }
    

    so that the string is moved into the function object.

    If you intent to call this function only once and want to move the string out of the function object again, you can use a non-const reference:

    void foo(char const* p) {
       string s = p;
       auto fun = bind([](string & s) {
          some_other_func(move(s));
       },move(s));
       fun();
    }
    

    Note that, if you don't want to use bind here but let the lambda object's constructor create a copy of s, moving the string out of the function object requires the mutable keyword:

    void foo(char const* p) {
       string s = p;
       auto fun = [=]() mutable {
          //            ^^^^^^^
          some_other_func(move(s));
       };
       fun();
    }
    

    because otherwise the closure type's operator() function will be const-qualified which in turn makes s a const-qualified string.

    In C++14 the lambda capture clause got a little more flexible. We can now write

    void foo(char const* p) {
       string s = p;
       auto fun = [s=move(s)]() mutable { // #1
          some_other_func(move(s));       // #2
       };
       fun();
    }
    

    where #1 moves the string value into the lambda object and #2 moves the string value out (depending on how some_other_func is declared exactly).

    0 讨论(0)
提交回复
热议问题