Reputation: 5917
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?
Upvotes: 16
Views: 15390
Reputation: 27028
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
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
Upvotes: 10
Reputation: 726639
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.
NULL
or nullptr
in C++11.
Upvotes: 4
Reputation: 120711
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.
Upvotes: 2