Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In a lambda, how reference is being captured by value

Tags:

c++

c++11

lambda

If a variable of reference type is captured in a lambda by value, is the referenced object copied or is it captured by reference?

Small sample with question:

#include <iostream>  struct Test {   int a; };  void testFunc(const Test &test) {   auto a = [=] {     // is 'test' passed to closure object as a copy     // or as a reference?     return test.a;   } ();   std::cout << a; }  int main() {   Test test{1};   testFunc(test); } 
like image 492
Yury Avatar asked Oct 30 '13 07:10

Yury


People also ask

Does lambda capture reference by value?

The mutable keyword is used so that the body of the lambda expression can modify its copies of the external variables x and y , which the lambda expression captures by value. Because the lambda expression captures the original variables x and y by value, their values remain 1 after the lambda executes.

What does it mean to lambda capture this?

The lambda is capturing an outside variable. 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 capture a variable in lambda C++?

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.

What is capture clause in lambda function in C++?

A capture clause of lambda definition is used to specify which variables are captured and whether they are captured by reference or by value. An empty capture closure [ ], indicates that no variables are used by lambda which means it can only access variables that are local to it.


1 Answers

By value. Compilable example:

class C { public:     C()     {         i = 0;     }      C(const C & source)     {         std::cout << "Copy ctor called\n";         i = source.i;     }      int i; };  void test(C & c) {     c.i = 20;      auto lambda = [=]() mutable {          c.i = 55;     };     lambda();      std::cout << c.i << "\n"; }  int main(int argc, char * argv[]) {     C c;     test(c);      getchar(); } 

Result:

Copy ctor called 20

I guess, that this paragraph of the C++ standard applies:

5.1.2 Lambda expressions

(...) 14. An entity is captured by copy if it is implicitly captured and the capture-default is = or if it is explicitly captured with a capture that does not include an &. For each entity captured by copy, an unnamed nonstatic data member is declared in the closure type. The declaration order of these members is unspecified. The type of such a data member is the type of the corresponding captured entity if the entity is not a reference to an object, or the referenced type otherwise. [ Note: If the captured entity is a reference to a function, the corresponding data member is also a reference to a function. —end note]

That actually makes sense - if local variables are passed by value and parameter passed by reference "acts" as a local variable in function, why would it be passed by reference instead of value?

like image 198
Spook Avatar answered Sep 18 '22 18:09

Spook