Returning an object or a pointer in C++

12,658

Solution 1

In C++, should my method return an object or a pointer to an object? How to decide?

Since C++11 we have move semantics in C++ which means that it as easy as before and now also fast to return by value. That should be the default.

What if it's an operator? How can I define?

Many operators such as operator= normally return a reference to *this

X& X::operator=(X rhs); 

You need to look that up for each operator if you would like to comply with the usual patterns (and you should). Start here: Operator overloading

As pointed out by Ed S. return value optimization also applies (even before C++11) meaning that often object you return need neither be copied or moved.

So, this is now the way to return stuff:

std::string getstring(){ 
   std::string foo("hello");
   foo+=" world";
   return foo;
}

The fact that I made a foo object here is not my point, even if you did just do return "hello world"; this is the way to go.

And one more thing - if the pointer turns to be a vector, how can I find out its size after returned? And if it's impossible, as I think it is, how should I proceed to correctly return an array without this limitation?

The same goes for all copyable or movable types in the standard (these are almost all types, for example vectors, sets, and what not), except a few exceptions. For example std::arrays do not gain from moving. They take time proportional to the amount of elements. There you could return it in a unique_ptr to avoid the copy.

typedef std::array<int,15> MyArray;
std::unique_ptr<MyArray> getArray(){ 
  std::unique_ptr<MyArray> someArrayObj(new MyArray());
  someArrayObj->at(3)=5;
  return someArrayObj;
}

int main(){
  auto x=getArray();
  std::cout << x->at(3) <<std::endl; // or since we know the index is right: (*x)[3]
}

Now, to avoid ever writing new anymore (except for experts in rare cases) you should use a helper function called make_unique. That will vastly help exception safety, and is as convenient:

std::unique_ptr<MyArray> getArray(){ 
  auto someArrayObj=make_unique<MyArray>();
  someArrayObj->at(3)=5;
  return someArrayObj;
}

For more motivation and the (really short) implementation of make_unique, have a look here: make_unique and perfect forwarding

Update

Now make_unique is part of the C++14 standard. If you don't have it, you can find and use the whole implementation from the proposal by S.T.L.:

Ideone example on how to do that

Solution 2

In C++, should my method return an object or a pointer to an object?

You should return an object by default. Usual exceptions are functions that return a subclass of a given class, and when returning nothing is a legal option for a function1.

What if it's an operator?

Operators return references or objects; although it is technically possible to return pointers from overloaded operators, it is not usually done.

And one more thing - if the pointer turns to be a vector, how can I find out it's size after returned?

I think you meant an array rather than a vector, because std::vector has a size() member function returning the size of the vector. Finding the size of a variable-length array is indeed not possible.

And if it's impossible, as I think it is, how should I proceed to correctly return an array without this limitation?

You should use std::vector, it does not limit you on the size or the type of elements that go into it.


1 In which case you return NULL or nullptr in C++11.

Solution 3

Unless there is some specific reason to use plain pointers, always return something memory-safe. In an estimated 95% of all cases, simply returning objects is fine, and then return-by-value is definitely the canonical thing to do (simple, efficient, good!).

The remaining 5% are mostly when the returned object is runtime-polymorphic; such an object can't be returned by value in C++ since that would happen on the stack. In such a case, you should return a smart pointer to the new object, in C++11 the standard choice is std::unique_ptr. There is also the case when you want to optionally return something, but that's IMO a case for a specific container, not for pointers, boost::optional or something like that.

Share:
12,658
Luan Nico
Author by

Luan Nico

I like programming, reading, playing video games, board games, RPG, and much more! Most importantly, I am #SOreadytohelp.

Updated on June 03, 2022

Comments

  • Luan Nico
    Luan Nico about 2 years

    In C++, should my method return an object or a pointer to an object? How to decide? What if it's an operator? How can I define?

    And one more thing - if the pointer turns to be a vector, how can I find out its size after returned? And if it's impossible, as I think it is, how should I proceed to correctly return an array without this limitation?

  • Ed S.
    Ed S. over 11 years
    And even before move semantics we had RVO, with hit or miss support for RVO across translation units.
  • Cubic
    Cubic over 11 years
    HASKELLLIKE_CLASS_MAYBE_MONAD is a pretty cute name.
  • Lightness Races in Orbit
    Lightness Races in Orbit over 11 years
    Will return "hello"; really break that? i.e. does the return value need to be named?
  • Ed S.
    Ed S. over 11 years
    No need to use std::array::at() when you know that the index is not out of range.
  • Johan Lundberg
    Johan Lundberg over 11 years
    @EdS. True, but as an example, the syntax for [] on a pointer is not as nice ;)
  • Ed S.
    Ed S. over 11 years
    @JohanLundberg: I suppose we'll just have to disagree there, but ok, fair enough.