Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

With C++ lambdas, what are the rules for capturing references by reference?

With C++ lambdas, what happens when you capture a reference by reference? Are you capturing a reference to a local object on the stack (the reference itself), or a reference to the object being referred to? Eg in the following code:

int& TestClass::returnReference()
{
        static int i=0;
        return i;
}

std::function<void ()> TestClass::testFunction()
{
        int& memberRef = this->someIntMember;
        int& intRef = returnReference();

        auto lambda =
        [&]
        {
                // What happens when you capture a reference by reference
                // like memberRef or intRef?
        };

        return lambda;
}
like image 615
Nick Kovac Avatar asked Apr 22 '16 11:04

Nick Kovac


People also ask

What is capture in lambda function?

A lambda expression can refer to identifiers declared outside the lambda expression. If the identifier is a local variable or a reference with automatic storage duration, it is an up-level reference and must be "captured" by the lambda expression.

How do you capture a variable in lambda C++?

To capture a variable by reference, we prepend an ampersand ( & ) to the variable name in the capture. Unlike variables that are captured by value, variables that are captured by reference are non-const, unless the variable they're capturing is const .

How many ways are there to capture the external variables in the lambda expression?

In our example, the lambda accesses, or captures, two variables from its enclosing scope: min_wage and upper_limit. There are two ways to capture variables with external references: Capture by copy. Capture by reference.

How do lambda functions work C#?

Lambda expressions in C# are used like anonymous functions, with the difference that in Lambda expressions you don't need to specify the type of the value that you input thus making it more flexible to use. The '=>' is the lambda operator which is used in all lambda expressions.

What is the use of lambda functions in C++?

C++ Lambda expression allows us to define anonymous function objects (functors) which can either be used inline or passed as an argument. Lambda expression was introduced in C++11 for creating anonymous functors in a more convenient and concise way.


1 Answers

The standard actually mandated it needed to capture the variable, not what it referred to. This was a bug in the standard, and the only case in C++ where this kind of thing could happen.

There is a defect report and suggested resolution (thanks @t.c.) that changed it to capture the referred-to eintity.

In theory, there is a low-cost reference-capture technique that captures the stack pointer and uses offsets known at the point of lambda declaration (plus maybe this) that would use the fact we need only capture a reference by variable not contents. However no compiler I know of used it, and the defect report implies that references you cannot alias into locals/globals cannot be treated this way.

In short, the standard says the wrong thing, but there is no practical problem as no compiler followed the letter of the standard, but rather did the right thing. And future compilers would have to be in violation of the suggested defect resolution to have the bad behaviour.

like image 85
Yakk - Adam Nevraumont Avatar answered Nov 14 '22 22:11

Yakk - Adam Nevraumont