views:

146

answers:

6

When you want to return an instance from a method, do you create the object and send a pointer back, or a reference back? Whats the correct method and the method signature for this?

+6  A: 

There are a lot of ways to do this in C++. Unfortunately most of them result in confusion on who is responsible for allocating and deallocating the object. There are two methods that I recommend:

// Return a real object, automatic stack allocation.
Foo GetFoo1()
{
   Foo f;
   // Init f.
   return f;
}

// Use a smart, reference counted pointer that handles deallocation itself.
boost::shared_ptr<Foo> GetFoo2()
{
   boost::shared_ptr<Foo> f(new Foo);
   // Init f
   return f;
}
Anders Abel
I agree with this comment. It should be noted that shared_ptr made it into TR1, and is implemented in both gcc and Visual Studio as std::tr1::shared_ptr. unique_ptr should be noted if you have well defined "sinks" and "sources"... but thats technically C++0x. If you're only using C++98... you can use auto_ptr for that. But unique_ptr is superior in every respect.
Dragontamer5788
What about a reference to a member (remember the original post was about a method not a function).
Martin York
I don't believe you can return a reference to a local object allocated on the stack. f will go out of scope when you return from GetFoo1
crazyx
naivnomore
Don't return a shared_ptr unless you are trying to enforce permanent use of shared_ptr. You can not get the pointer out once it's in one of these. Thus you can't assign to a scoped pointer, unique pointer, or anything else that might better serve the needs of the requesting client.
Noah Roberts
@navinomore wrong. I compiled code like that just to make sure and it crashed when I tried to operate on the return value. It goes out of scope and gets deleted as soon as you exit GetFoo1.
crazyx
@crazyx: If fact naivnomor is correct. The value is being returned by value. This means that it will be copied out of the function using the copy constructor (unless RVO is being applied by the compiler) but once the function has returned the values has (in effect) already been moved out of the scope of the function.
Martin York
+3  A: 

If I'm creating an instance purely to return, I would return by value as first preference.

Only if the object type was not practically copyable would I consider returning via a smart pointer encapsulating the transfer of ownership.

Returning a reference I reserve for returning a reference to an object whose ownership isn't being transferred out of the function, that is it is already owned by something else and it's existence is guaranteed until a defined time after the function returns.

Charles Bailey
+2  A: 

If you're referring to something like a Factory Method, typically you return a pointer. Better still, return a smart pointer and you don't create more leaks by virtue of using a raw pointer.

Example:

std::auto_ptr<Gizmo>  MyFactory::CreateGizmo()
{
  return new Gizmo;
}
John Dibling
+4  A: 

Either return by value (people incorrectly assume that this is slow) or, if you're returning an override of a polymorphic type, return an auto_ptr (or better a unique_ptr in C++0x).

The reason you do NOT use a shared_ptr is that you can never get your pointer out of it and use a different ownership semantic.

Never return a reference to a local instance.

Noah Roberts
Although a little out of date, there's a good Scott Meyers article along these same lines as this answer here: http://www.aristeia.com/Papers/resourceReturnProblem.txt
SCFrench
A: 

This really depends on the scope of your instance which controls the lifetime of the instance. If this is a local instance, you may return by value but will incur the cost of constructing & destructing the object twice (unless you use RVO). The other option is to return a pointer by constructing the object in the heap inside your function. However, with this approach the client will be responsible for deleting the allocated memory & is always prone to memory leaks. This is why you will need to use some kind of a smart pointer. Anders Abel code clearly illustrates the above two approaches with code examples. BTW, you cannot return a reference to a local instance since the instance will go out of scope once the function ends.

naivnomore
+1  A: 

The answer depends on what exactly you are doing and who is responsible for deallocating.

First method: allocate on the heap and return. Who ever called the function will be responsible for deleting the returned pointer.

SomeObject* constructObject ()
{
   SomeObject* obj = new SomeObject ();
   return obj;
}

Then in some other function

void functionThatNeedsObject ()
{
   SomeObject* obj = constructObject ();
   //You must delete obj when done
}

Second method: Return a reference. You must be careful not to go out of scope by returning local or temporary variables.

Dont do this:

int& DoubleValue(int nX)
{
   int nValue = nX * 2;
   return nValue; // return a reference to nValue here
} // nValue goes out of scope here

You can return references to member variables or variables passed as arguments to the function.

SomeStruct& RefFunction(SomeStruct& nX, SomeStruct& nY)
{
    return nX;
} //nX is still in scope because it was passed to us
crazyx