Assigning the result of a function returning Foo to const Foo &

I have a function that returns an object of type Foo :

 Foo getFoo(); 

I know that the following will compile and work, but why should I do this?

 const Foo& myFoo = getFoo(); 

For me, the following is more readable and does not make me remember that C ++ allows me to assign an r-value to a const reference:

 const Foo myFoo = getFoo(); 

What is the difference between the two? Why should I use the first in a second? Why should I use the second during the first?

+7
c ++
source share
4 answers

Contrary to popular belief, there is no guarantee that assigning the result of a function that returns an object by value to a const reference will result in fewer copies than assigning it to the object itself.

When you assign an rvalue to a const link, the compiler can link the link in one of two ways. He can create a new temporary one by copying the rvalue and linking the link to it, or he can bind the link directly to the rvalue itself.

If the compiler cannot do the β€œobvious” optimization to remove the temporary and hide the copy constructor for the getFoo return value, how likely is it to be able to make a more efficient form of binding the r value for the const link without creating a new temporary?

One reason for using a constant reference would be to make the function more resistant to potential slicing. If the return type was actually a type obtained from Foo , then assigning a const const reference would be guaranteed not to be truncated, even if the compiler made a temporary object from the rvalue returned by the function. The compiler also generates the correct call to the destructor of the derived class, regardless of whether the destructor in the base class is virtual or not. This is because the type of the temporary object created is based on the type of the expression being assigned, and not on the type of link initialization.

Note that the question of how many copies of the return value is made is completely separate from optimizing the return value and optimizing the named return value. These optimizations relate to eliminating a copy of either the rvalue result of evaluating the returned expression, or the named local variable in the return value of the function in the body of the function itself. Obviously, in the best possible case, it is possible to optimize both the optimization of the return value and the temporary value of the return value, which can be eliminated, which will not lead to copies on the returned object.

+4
source share

I think GotW # 88 answers it best

+4
source share

It is acceptable to use the following pattern:

 void foo(const SomeType &); foo(SomeType(bar)) 

In this case, a temporary SomeType is created and passed to foo. Most likely, the fact that you can also have permalinks to the stack in time is a side effect of the language used to define this behavior in the standard. Please note that, as mentioned in the comments, the temporary lifetime extends as it is done in the link itself.

+1
source share

There may be several reasons:

what if you do not want to refer to a const object? For example, this will not work:

     const Foo & myFoo = getFoo ();
     myFoo.myfield = x;

Or, what if you return a temp object from getFoo ()? This will warn about the return of the link (or address) to the local folder:

     const Foo & getFoo (void)
     {
        Foo localFoo ();
        // do the things you want to localFoo
        return (localFoo);
     }

the const Foo& myFoo = getFoo() do almost the same thing as Foo myFoo = getFoo() , so the argument that there is a performance value to return ref ref is not valid. I believe that there is no problem returning objects of a reasonable size.

Disclaimer - I have not tried these examples on gcc. Your mileage may be adjusted accordingly.

0
source share

All Articles