Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is return value always a temporary?

This page says a strange thing :-

The temporaries are created only if your program does not copy the return value to an object and example given is

UDT Func1(); // Declare a function that returns a user-defined type.
            ...

Func1();        //  Call Func1, but discard return value.
               //  A temporary object is created to store the return
              //   value

but if i have done :-

UDT obj=Fuct1;

It appears to me that it will also create a temporary as follow:-

Func() constructs a local object. Next, this local object is copy-constructed on the caller's stack, making a temporary object that is used as the argument of obj's copy-constructor.

Am I wrong?
Is this has something to do with copy elision?

like image 872
T.J. Avatar asked Sep 07 '25 09:09

T.J.


2 Answers

The page you cite it a description of the behavior of a specific compiler. Formally: the return value is always a temporary. In contexts where that temporary is used as the argument of a copy constructor (the object is copied), the standard gives explicit authorization for the compiler to elide the copy, “merging” the temporary with the named variable it is initializing. All the sentence you quote is saying is that this specific compiler always does his optimization (as do most other compilers).

like image 115
James Kanze Avatar answered Sep 09 '25 04:09

James Kanze


This page is Microsoft specific. It's true that the standard permits to do two, one or zero calls to the copy constructor during function return (this is called copy elision). In fact one call is always sufficient.

Suppose you write:

A f(int x) {
    return A(x);
}

void g() {
    A r = f(10);
}

The way MSVC implements this is:

void f_impl(A* r, int x) {
    new((void*)r) A(x); // construct the return value into r
}

void g_impl() {
    A r = __uninitialized__;
    f_impl(&r, 10);
}

Here you see zero calls to the copy constructor and no temporaries.

If you call f like this:

void g() {
    f(10);
}

Then the compiler still needs to construct the return value somewhere, so it creates a temporary:

void g_impl() {
    A r = __uninitialized__;
    f_impl(&r, 10);
    r.~A(); // destruct temporary
}

When it calls the copy constructor? In the implementation of f when it can't know which f's local will be returned. E.g. this:

A f(int x)
{
    A r1;
    A r2;
    // ...do something complicated modifying both r1 and r2...
    if(x)
        return r1;
    // ...do something complicated...
    return r2;
}

Is translated to something like this:

void f_impl(A* r, int x)
{
    A r1;
    A r2;
    // ...do something complicated modifying both r1 and r2...
    if(x)
    {
        new((void*)r) A(r1); // copy construct r1
        return;
    }
    // ...do something complicated...
    new((void*)r) A(r2); // copy construct r2
}
like image 24
Yakov Galka Avatar answered Sep 09 '25 03:09

Yakov Galka