tower120
tower120

Reputation: 5255

C++ extending lifetime of &&

In the following example:

http://coliru.stacked-crooked.com/a/7a1df22bb73f6030

struct D{
    int i;    
    auto test2(int&& j){
        return [&](){       // captured by reference!
            cout << i*(j);
        };
    }    
};

int main()
{
    D d{10};
    {
      auto fn = d.test2(10);
      fn();                     // 1. wrong result here

      d.test2(10)();            // 2. but ok here
    }
}

Why does d.test2(10)(); work?

Should it really work, or thats just my undefined behavior equals correct result?

P.S. After reading this I see only one explanation: in (2) temporary lifetime prolongs till the end of the expression, and call happens in the same expression with && crteation; while (1) actually consists from 2 expressions:

a temporary bound to a reference parameter in a function call exists until the end of the full expression containing that function call: if the function returns a reference, which outlives the full expression, it becomes a dangling reference.

Is this the case?

Upvotes: 2

Views: 370

Answers (2)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275350

A temporary object lasts until the end of the line (well, full expression) where it is created, unless the lifetime is extended.

Your code does not extend the lifetimes of any temporaries. Lifetime extension through binding to references does not "commute", only the first binding extends lifetime.

So the furst case is UB as you have a dangling reference. The referred to temporary goes away st the end of the line: on the next line uou follow the reference, and chaos hapens.

In the second case, your reference does not extend the lifetime of the temporary, but the temporary lasts longer than the reference that binds to it does! They both die at the end of the line, in reverse order of construction.

So the call works.

Upvotes: 4

user6398035
user6398035

Reputation: 1

Should it really work, or thats just my undefined behavior equals correct result?

Seems like it. In the example you linked, you have these warnings:

warning: '<anonymous>' is used uninitialized in this function [-Wuninitialized]

Uninitialized objects have indetermine values, and trying to access those values results in undefined behavior.

Upvotes: -1

Related Questions