How does prvalue works?

360 Views Asked by At

I have read a few posts on SO about prvalue and guaranteed copy elision (especially this one). But I am still confused about how prvalue works.

Consider the following code (C++17):

class Y
{
public:
    Y() { cout << "Y dctor\n"; }
};

class X
{
public:
    X() { cout << "X dctor\n"; }
    X(const X&) { cout << "copy X\n"; }
    X(const Y&) { cout << "copy Y\n"; }
};

X fun()
{
    Y y;
    return X(y);
}

int main()
{
    X x1 = fun();
}

In my current understanding, X(y) is a prvalue, and this prvalue is used to initialize the return value of fun(), which is also a prvalue (so the prvalue is "copied and passed down"). And this (returned) prvalue is then used to initialize the variable x1 by calling X(y) to construct x1. There is no temporary created or object copied in this process, only prvalue (which is not object in this circumstance) passing.

However, my question is, at the point when the return value of fun() has just been initialized by the prvalue of X(y), the call of fun() should have been finished, and thus the local variable y should have been destroyed. But then, how could x1 be constructed from the returned prvalue by calling X(y) without the object of y?


A follow-up question is about when we return named variable. Consider two more functions:

X g()
{
    X x;
    return x;
}

X h()
{
    return g();
}

int main()
{
    X x2 = h();
}

From the answer I linked above, it is said that:

... nothing changes for named return value optimization (NRVO).

So does this mean what happens above in C++14 happens exactly the same in C++17 for each implementation?

Since I don't understand prvalue well, I don't understand how exactly the compiler is dealing with the above in C++17. I know that eventually x will be copied directly to x2 (and we need an accessible copy/move constructor for that to happen), but to me, after the point return g();, X x2 = h(); looks similar enough to X x1 = fun(); (as g() and h() are all prvalues). So I wonder if the concept of prvalue in C++17 will make the internal process different from what happens internally in C++14 for the above code?

0

There are 0 best solutions below