简体   繁体   中英

C++11 lambda: mixed capture list

Can somebody please show me examples of the following:

1) Lambda that captures x by value. y by reference. What do the rest default to, if unspecified?

2) Lambda that captures x by value. y by reference, all else by value.

3) Lambda that captures x by value. y by reference, all else by reference.

Also, is it allowed that 2 lambdas in the same scope have the same capture signature, such as both be [] , or both be [&x, =]

Thanks

1) [x, &y](){} rest is not captured

2) [=, &y](){}

3) [&, x](){}

The capture-list is a comma-separated list of zero or more captures, optionally beginning with the capture-default. The only capture defaults are & (by reference) and = (by value). If a capture-default is used, no other captures may use the same capture type. Any capture may appear only once.

Also, is it allowed that 2 lambdas in the same scope have the same capture signature, such as both be [], or both be [&x, =]

Of course it is allowed. Every lambda will be distinct object and have its distinct type. If you capture variable by value in two lambdas, then every lambda will have its copy. If you capture variable by reference in two lambdas, then every lambda will have a reference to the same captured variable.

Can just write some examples:

int x = 7, y = 12, z = 24;

auto lambda1 = [x, &y]{
    // can't do this...
    // std::cout << "x=" << x << ", y=" << y << ", z=" << z << std::endl;
    std::cout << "x=" << x << ", y=" << y << std::endl;
};

auto lambda2 = [=, x, &y]{
    std::cout << "x=" << x << ", y=" << y << ", z=" << z << std::endl;
};

auto lambda3 = [&, x, &y]{
    std::cout << "x=" << x << ", y=" << y << ", z=" << z << std::endl;
};

++x, ++y, ++z;
lambda1();
lambda2();
lambda3();

Now, lambda1 here can't use z . There is no "implicit" capture, since we don't have = or & specified and z doesn't appear in the capture list, we cannot print z there. So that's an error if we tried to use the line I have commented out.

The other two are fine and would print 7, 13, 24, and 7, 13, 25, respectively. Note that the = and & must come first. Also, given that we're capturing all by value/reference, one of the other captures is redundant, so we could've done:

auto lambda2 = [=, &y]{ ... };
auto lambda3 = [&, x]{ ... };

1)

[x,&y](){} // the rest is not captured, eg `z` is not defined in the scope

2)

[=,&y](){} // `=` is capture everything by value

3)

[&,x](){} // `&` is capture everything by reference

To quote Bjarne from his C++11 FAQ :

The [&] is a "capture list" specifying that local names used will be passed by reference. We could have said that we wanted to "capture" only v, we could have said so: [&v]. Had we wanted to pass v by value, we could have said so: [=v]. Capture nothing is [], capture all by references is [&], and capture all by value is [=]. If an action is neither common nor simple, I recommend using a named function object or function.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM