Reputation: 14419
What is the difference between these?
MyType myFunction();
MyType t = myFunction();
AND
MyType &myFunction();
MyType t = myFunction();
AND
const MyType &myFunction();
MyType t = myFunction();
What is going on behind the scenes?
Upvotes: 2
Views: 162
Reputation: 8968
I guess what you want to do is something like:
MyType *myFuntion()
{
MyType *t = new MyType;
// do something with t
return t;
}
// ... somewhere else ...
MyType *t = myFunction();
i.e. you construct a new object inside a function and return a pointer to it. Don't forget to call
delete t;
somewhere later!
Upvotes: -1
Reputation: 208436
In the three cases the second line is common:
MyType t = myFunction();
That line gets the result of calling myFunction
and uses it to copy-construct a new element of MyType
called t
.
Now on the differences. In the first case you are returning by value, which means that (semantically), the compiler will create a copy of the object that is in the return
statement inside myFunction
and then use that copy as the source for the copy construction of t
. The compiler will most probably elide the copies (at least the second).
In the other two cases, the functions return references to some other object. If the objects are locals, then it is Undefined Behavior. The difference between the two is whether the reference returned can be used to modify the referred object or not, and this might impact what copy constructor is used or if it can be used at all. Beware that the object from which you are obtaining the reference must outlive the function call, or you will be causing undefined behavior.
// an example where it matters:
typedef std::auto_ptr<int> MyType;
MyType t = myFunction();
Because std::auto_ptr
modifies the right hand side on assignment, the previous code will only work if the returned reference is non-const.
Luchian points out that returning a reference will most likely be undefined behavior, so when would it not be? When the object from which the reference was obtained outlives the uses of the reference. That is the basic building block of the Meyers singleton:
// an example where returning a reference is correct
MyType & myFunction() {
static MyType instance; // Note static storage duration!
return instance;
}
Or any plain accessor that returns a reference to a subobject. Some of the common cases are operator[]
in containers (they usually don't copy the value, but return a reference to the stored data).
But it is true that more often than not, functions don't return statically lived objects, but rather locals.
Upvotes: 3
Reputation: 4291
Most answers get things correct save for one little detail.
const MyType& t = myFunction();
It would seem that if myFunction() returns a temporary variable this would be undefined behavior, but in reality it's not. This is not UB, and in fact the const reference extends the lifetime of the temporary to the lifetime of the const reference. In fact this is the one version with most potential for compiler optimization and also gives away an important lesson, that one should always take return values into a const reference when possible.
Upvotes: 0
Reputation: 258628
I'm assuming these are free functions.
MyType myFunction();
MyType t = myFunction();
returns a MyType
object by value. Theoretically, the object created inside myFunction
is copied on return. Practically, RVO will most likely occur.
MyType &myFunction();
MyType t = myFunction();
returns by reference. This will most likely be undefined behavior, since it's illegal to return local objects by reference. However, if myFunctions
is a member function, you could return a MyType
that is a member of the class and it would be ok, as long as the instance outlives t
.
For the second code snippet, you should get a warning - "returning local variable by reference" or something similar.
Upvotes: 1