Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any difference between these forms : returnType vs returnType &?

Consider these free standalone functions:

          std::vector<int>& f();   //reference
          std::vector<int>  g();   //value

/*const*/ std::vector<int>&  f1 = f();  //reference
          std::vector<int>   f2 = f();  //value

/*const*/ std::vector<int>&  g1 = g();  //reference
          std::vector<int>   g2 = g();  //value

Is there any difference between :

  • f() and g(). Its easy question, but still I would like to hear some detail commentary on them, as it might help understanding the answer of the next questions.

  • f1 and f2. Will they be same original object from f(), or f2 will be a copy of the original? Uncommenting const will make any difference?

  • g1 and g2. Will they be same original object from g(), or g2 will be a copy of the original? Uncommenting const will make any difference?

What if f() and g() are member functions, and each returns member data, not some local variable? Will it make any difference in the answer of the above questions?

Please try including all the pitfalls and important points in your answer, and don't consider RVO or any other optimization by compiler. I want to know what C++ is, not what compilers do. If you talk about optimizations, please explicitly mention it, so that I dont mix language features with compiler features.

like image 241
Nawaz Avatar asked Feb 25 '23 00:02

Nawaz


1 Answers

f() returns a reference to an object; returning from it does not copy any object. g() returns a copy of an object, at least conceptually.

std::vector<int>&  f1 = f();  //reference

f1 refers to the object to which f() returned a reference. No copies are made. Const-qualification of the reference does not make a difference here (as far as copying is concerned; obviously it affects what can be done with the object).

std::vector<int>   f2 = f();  //value

f2 is a copy of the object to which f() returned a reference.

std::vector<int>&  g1 = g();  //reference

This is invalid. A non-const reference cannot be bound to a temporary object.

If the reference is const-qualified, then this line is effectively the same as the next line: a copy of the object returned by g() is made, the reference is bound to that copy, and that copy is given the lifetime of the reference (it is destroyed when the reference is "destroyed").

std::vector<int>   g2 = g();  //value

g2 is a copy of the object returned by g(). Whether a copy is made (and how many copies may be made) depends on compiler optimizations.

What if f() and g() are member functions, and each returns member data, not some local variable?

If f() returns a reference to a local variable then the program is incorrect and yields undefined behavior if you attempt to use the reference because the referred-to object ceases to exist when the function returns.

If f() returns a reference to a member variable, a dynamically allocated object, or an object with static or thread local storage duration, then the reference is valid for the lifetime of that object (or to another object of the same type constructed at the same location in memory as the object to which the reference was returned, though the utility of this is limited to a select few scenarios).

It doesn't matter what g() returns because a copy is always made (at least conceptually).

like image 152
James McNellis Avatar answered Mar 02 '23 00:03

James McNellis