When to return a pointer, scalar and reference in C++?

theone picture theone · Aug 7, 2010 · Viewed 10.5k times · Source

I'm moving from Java to C++ and am a bit confused of the language's flexibility. One point is that there are three ways to store objects: A pointer, a reference and a scalar (storing the object itself if I understand it correctly).

I tend to use references where possible, because that is as close to Java as possible. In some cases, e.g. getters for derived attributes, this is not possible:

MyType &MyClass::getSomeAttribute() {
    MyType t;
    return t;
}

This does not compile, because t exists only within the scope of getSomeAttribute() and if I return a reference to it, it would point nowhere before the client can use it.

Therefore I'm left with two options:

  1. Return a pointer
  2. Return a scalar

Returning a pointer would look like this:

MyType *MyClass::getSomeAttribute() {
    MyType *t = new MyType;
    return t;
}

This'd work, but the client would have to check this pointer for NULL in order to be really sure, something that's not necessary with references. Another problem is that the caller would have to make sure that t is deallocated, I'd rather not deal with that if I can avoid it.

The alternative would be to return the object itself (scalar):

MyType MyClass::getSomeAttribute() {
    MyType t;
    return t;
}

That's pretty straightforward and just what I want in this case: It feels like a reference and it can't be null. If the object is out of scope in the client's code, it is deleted. Pretty handy. However, I rarely see anyone doing that, is there a reason for that? Is there some kind of performance problem if I return a scalar instead of a pointer or reference?

What is the most common/elegant approach to handle this problem?

Answer

jalf picture jalf · Aug 7, 2010

Return by value. The compiler can optimize away the copy, so the end result is what you want. An object is created, and returned to the caller.

I think the reason why you rarely see people do this is because you're looking at the wrong C++ code. ;) Most people coming from Java feel uncomfortable doing something like this, so they call new all over the place. And then they get memory leaks all over the place, have to check for NULL and all the other problems that can cause. :)

It might also be worth pointing out that C++ references have very little in common with Java references. A reference in Java is much more similar to a pointer (it can be reseated, or set to NULL). In fact the only real differences are that a pointer can point to a garbage value as well (if it is uninitialized, or it points to an object that has gone out of scope), and that you can do pointer arithmetics on a pointer into an array. A C++ references is an alias for an object. A Java reference doesn't behave like that.