简体   繁体   中英

C++: Return by reference to return by value

I've been reading Myers book and came across the item on returning by reference/pointer vs by value. The point is, if our function for example is like this:

ClassA& AddSomething(ClassA classA)
{
  ClassA tempClassA;
  //... do something on tempClassA
  return tempClassA;
}

This would not work because we are returning a reference to a object that was created on the stack and it is dead now that the function is done.

He gives two solutions:

  1. Using a local static ClassA inside the function. This has its problems but atleast we can be sure that object exists.
  2. Return as an object:

     ClassA AddSomething(ClassA classA) { ClassA tempClassA; //... do something on tempClassA return tempClassA; } 

Now if I'm to do:

ClassA obj1;
ClassA obj2 = AddSomething(obj1);

My confusion now is, when executing this line:

  1. A 'copy' of tempClassA is made and passed to the copy constructor of ClassA (to initialize obj2)? OR
  2. tempClassA is passed itself to the copy constructor of ClassA, because copy constructor takes a reference.

So basically, whats passed to the copy constructor is a reference to tempClassA (which was created in stack inside the function) or a reference to a copy of tempClassA.

Also, another question I have is, I have read that if I get a reference of a function local variable, in that case the local variable will not be deleted. For example,

ClassA & classRef = AddSomething(obj1);

In this case, if AddSomething() is returning a reference, then classRef not be pointing to a deleted reference because the local variable will be retained. Have I understood this correctly?

At worst, you're right: a copy of tempClassA is passed to the copy constructor. But compilers are allowed to eliminate that copy and construct the result in place form tempClassA . This is known as the "Return Value Optimization", or RVO. I don't know of a compiler that doesn't do this.

When an object is returned by value, there are two copies taking place: one from the local variable into the return value, and one from the return value into the target object. However, the implementation is allowed to elide one or both of these copies; this is called return value optimisation (RVO) in the first case, and copy elision in the second.

Object some_function() {
    return Object();    // copy Object() into return value; candidate for RVO
}
Object another_function() {
    Object obj;
    return obj;         // copy obj into return value; candidate for NRVO
}
Object result = some_function();   // copy return value into result; candidate for copy elision

The second function above is a candidate for a refinement type of RVO called named return value optimisation; the simplest form of RVO applies only to return statements that construct the return value inplace.

Regarding your second question, lifetime extension only applies to const references to objects returned by value; your code in the second question will not extend the lifetime of any object. See Returning temporary object and binding to const reference for more details.

You can never return a function local variable by reference. It would NOT work even if you used const reference to capture the returned value like this:

const ClassA& classRef = AddSomething(obj1);

Because if AddSomething returns a local object by reference, it'll be a dangling reference to a non-existing object by the time classRef gets to reference it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM