Cheetah
Cheetah

Reputation: 14419

Difference between function types

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

Answers (4)

steffen
steffen

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

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

Ylisar
Ylisar

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

Luchian Grigore
Luchian Grigore

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

Related Questions