# C++11 lambda, modifying copied value

This topic is 1112 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

int fooVar = 10;
std::function<void()> fooFunction =  [=]() {
fooVar = 12;
};


Trying to modify foorVar in that lambda results in an error, because its not an lvaue.

Why is the copied value made constant?!

##### Share on other sites
Because const data is safer than mutable data. This also makes the lambda more composable. And C++ says so.

As well as to try to prevent people from making the same mistake you've made in your example code - assuming that the change you made in the lambda is visible outside the lambda because the variable has the same name even though it's a completely different value.

What's the point of modifying a value that no one can see? The only one who can read your changed fooVar is the lambda itself, the external fooVar will be untouched because you captured by value.

If you absolutely want the copy to be mutable, you can add the mutable flag to it. But you should generally avoid doing that as other people may not expect a function to return different results when given the same parameters. Edited by SmkViper

##### Share on other sites

It makes sense if you want to do something like:

int counter = 10;
std::function<void()> fooFunction = [=]() {
while(counter--) {
// do important things
}
}

##### Share on other sites

It makes sense if you want to do something like:

But in your example, there is no reason for counter to exist outside the lambda. It always starts at 10 and always ends at 0. So counter could always exist entirely in the lambda.

Or pass it as a parameter. Since it isn't actually modifying counter, it is modifying a copy of counter.

##### Share on other sites

But in your example, there is no reason for counter to exist outside the lambda. It always starts at 10 and always ends at 0.

Assuming counter isn't defined as int counter = 10; but is something dynamic. Does your argument still hold?

##### Share on other sites

Assuming counter isn't defined as int counter = 10; but is something dynamic. Does your argument still hold?

In a sense, yes. You're not actually manipulating counter, but a copy of counter. The type is irrelevant. It doesn't need to be captured by the lambda, just passed as a parameter. Which for readability would make more sense (in my mind), since that defines it as an input affecting the function.

You probably don't want to be capturing everything by value anyway, as this could be very expensive.

##### Share on other sites

If you mark the lambda is mutable, the operator() will not be marked const, so you can modify the fooVar member.

int fooVar = 10;
std::function<void()> fooFunction =  [=]()mutable {
fooVar = 12; // totally fine now!
};


Keeping in mind, of course, that this happens, because it was copied by value:

fooFunction();
assert(fooVar == 12, "Huh?"); // this fires - function didn't modify this variable


##### Share on other sites

If you mark the lambda is mutable, the operator() will not be marked const, so you can modify the fooVar member.

But also note that if you do this, you'll need to be very careful about how many times fooFunction is invoked (since the second invocation won't behave identically to the first), as well as if the functor itself it is ever copied, or only ever referenced (and if copied, whether the copy happens before or after any invocations).

1. 1
2. 2
3. 3
Rutin
16
4. 4
JoeJ
13
5. 5

• 9
• 14
• 10
• 25
• 9
• ### Forum Statistics

• Total Topics
632645
• Total Posts
3007632
• ### Who's Online (See full list)

There are no registered users currently online

×