Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ best practice: Returning reference vs. object

Tags:

c++

I'm trying to learn C++, and trying to understand returning objects. I seem to see 2 ways of doing this, and need to understand what is the best practice.

Option 1:

QList<Weight *> ret;
Weight *weight = new Weight(cname, "Weight");
ret.append(weight);
ret.append(c);
return &ret;

Option 2:

QList<Weight *> *ret = new QList();
Weight *weight = new Weight(cname, "Weight");
ret->append(weight);
ret->append(c);
return ret;

(of course, I may not understand this yet either).

Which way is considered best-practice, and should be followed?

like image 374
Mike Crowe Avatar asked Mar 23 '10 04:03

Mike Crowe


People also ask

Which is generally more efficient a function that returns an object by reference or a function that returns an object by value?

Returning the object should be used in most cases because of an optimsation called copy elision. However, depending on how your function is intended to be used, it may be better to pass the object by reference.

When should I return by reference?

Objects returned by reference must live beyond the scope of the function returning the reference, or a dangling reference will result. Never return a local variable by reference.

Are objects returned by reference?

User-defined functions and class methods can define return types as object references (as class or interface types). When an object is passed locally, class instances are always returned by reference. Thus, only a reference to an object is returned, not the object itself.


3 Answers

Option 1 is defective. When you declare an object

QList<Weight *> ret; 

it only lives in the local scope. It is destroyed when the function exits. However, you can make this work with

return ret; // no "&" 

Now, although ret is destroyed, a copy is made first and passed back to the caller.

This is the generally preferred methodology. In fact, the copy-and-destroy operation (which accomplishes nothing, really) is usually elided, or optimized out and you get a fast, elegant program.

Option 2 works, but then you have a pointer to the heap. One way of looking at C++ is that the purpose of the language is to avoid manual memory management such as that. Sometimes you do want to manage objects on the heap, but option 1 still allows that:

QList<Weight *> *myList = new QList<Weight *>( getWeights() ); 

where getWeights is your example function. (In this case, you may have to define a copy constructor QList::QList( QList const & ), but like the previous example, it will probably not get called.)

Likewise, you probably should avoid having a list of pointers. The list should store the objects directly. Try using std::list… practice with the language features is more important than practice implementing data structures.

like image 126
Potatoswatter Avatar answered Sep 24 '22 03:09

Potatoswatter


Use the option #1 with a slight change; instead of returning a reference to the locally created object, return its copy.

i.e. return ret;

Most C++ compilers perform Return value optimization (RVO) to optimize away the temporary object created to hold a function's return value.

like image 21
missingfaktor Avatar answered Sep 25 '22 03:09

missingfaktor


In general, you should never return a reference or a pointer. Instead, return a copy of the object or return a smart pointer class which owns the object. In general, use static storage allocation unless the size varies at runtime or the lifetime of the object requires that it be allocated using dynamic storage allocation.

As has been pointed out, your example of returning by reference returns a reference to an object that no longer exists (since it has gone out of scope) and hence are invoking undefined behavior. This is the reason you should never return a reference. You should never return a raw pointer, because ownership is unclear.

It should also be noted that returning by value is incredibly cheap due to return-value optimization (RVO), and will soon be even cheaper due to the introduction of rvalue references.

like image 45
Michael Aaron Safyan Avatar answered Sep 21 '22 03:09

Michael Aaron Safyan