Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++0x: Capture By Value for Lambda, always a copy?

Is the compiler allowed to eliminate the copy that is required for the by-value capture?

vector<Image> movie1;
apply( [=movie1](){ return movie1.size(); } );
  • Is there any circumstance that the compiler does not need to copy movie1?
    • Maybe if the compiler could know, that apply does not actually change movie1?
    • Or does it help that Lambdas are by default const functors in any case?
  • Does it help at all that vector has a move constructor and move assign?
    • If yes, is it required to add these to Image as well, to prevent an expensive copy here?
  • Is there a difference in the mechanism when and how a copy is required for by-value capture compared to by-value arguments? eg. void operate(vector<Image> movie)?
like image 352
towi Avatar asked Mar 12 '11 14:03

towi


People also ask

How do you capture a variable in lambda function?

Much like functions can change the value of arguments passed by reference, we can also capture variables by reference to allow our lambda to affect the value of the argument. To capture a variable by reference, we prepend an ampersand ( & ) to the variable name in the capture.

How do you write lambda in copy?

Lambda Symbol (λ)

What does it mean to lambda capture this?

A lambda is a syntax for creating a class. Capturing a variable means that variable is passed to the constructor for that class. A lambda can specify whether it's passed by reference or by value.

How do you call a lambda in C++?

A lambda is also just a function object, so you need to have a () to call it, there is no way around it (except of course some function that invokes the lambda like std::invoke ). If you want you can drop the () after the capture list, because your lambda doesn't take any parameters.


2 Answers

I'm fairly sure it cannot.

Even if the outer function no longer explicitly uses the variable, moving the variable would change the semantics of destruction.

Having move constructors for Image doesn't help, a vector can move or swap without moving its elements.

If the variable is read-only from this point forward, why not capture by reference? You could even create a const reference and capture that.

If the variable is not read-only, the copy is required. It doesn't matter whether the outer function or the lambda performs the modification, the compiler cannot allow that modification to become visible to the other.

The only difference I see between by-value capture and by-value argument passing is that the capture is named, it cannot be a temporary. So argument passing optimizations applicable to temporaries cannot be used.

like image 61
Ben Voigt Avatar answered Oct 24 '22 02:10

Ben Voigt


There is always the "as-if" rule. As long as it looks as if the rules had been followed, the compiler can do whatever it likes. So for objects where the copy constructor and destructor have no side effects, and where no changes are made to the copy, or the original object isn't accessed afterwards (so no one will notice if we make changes to the object), the compiler could prove that eliminating the copy is legal under the "as-if" rule.

But other than that, no, it can't just eliminate the copy, as @Ben said. The "regular" copy elision rules don't cover this case.

like image 27
jalf Avatar answered Oct 24 '22 02:10

jalf