I have a member function with an object type as the return value type:
MyObject myfunction(parameters) {
if (some condition) {
return MyObject(parameters);
} else {
... no valid object can be created ...
}
}
Under certain conditions (checked for in the function body) an object of type MyObject cannot be created and returned.
Beeing just an occasional c++ programmer I can spontaneously come up with three solutions:
- Changing the return value type to * MyObject and returning nullptr if no valid object can be created (C++11), then checking for equality to nullptr in the calling code.
- Throwing an exception if no object can be created and catching that one in the calling code.
- Creating an object with some values that I define as invalid and check for that before using the returned object.
What would be the standard way of dealing with such a situation and the best solution in terms of performance? … or some obvious work-around that I just don’t see …
A state-of-the-art C++11 solution would be perfect 🙂
My thoughts so far:
Solution 1 seems OK, but is C++11 only and I would have to create the returned object on the heap in order to be able to pass it to the main program (returning the object itself to the calling function, thus keeping it in the stack might be quicker for small objects?).
Solution 2 might be slower and leads to verbose coding in the main program.
Solution 3 is probably the slowest (an object is created in vain) and not very convenient to check for in the main program.
For my code no valid return object is rather the default situation than the exception and the created object is rather small, but general considerations considering different cases are certainly useful for other readers’ applications …
Thanks a lot to all of you for help 🙂
All 3 of your suggested solutions are valid and common, depending on the circumstances.
If being unable to create the object is an error condition that is likely to cause the calling function to have to abort, back up and retry, or take other drastic measures, then throw an exception.
If inability to create the object is a routine event, and you expect the caller to check if an object was created and proceed fairly normally in either case, returning null is a good solution.
If there’s a reasonable dummy or blank object that can be created, that’s a fine solution. But this is pretty rare. You should only do this if the caller will actually process the dummy object.
If you return a null pointer and then you find that every place you call this function you are writing
Then you might as well just throw the exception inside the function.
Worse, if you are writing:
Then you are just simulating exception handling with an IF statement. Use a real exception.
On the other hand, if you throw an exception and then you find you are regularly writing:
Well then, you would have been better off to just return the null.
I’ve occasionally created dummy objects. The most common case is when a function returns a collection, like an array or linked list, and if I find no data to put in the collection, then return a collection with zero elements. Then the caller loops through the elements in the collection, and if there are none, that’s just fine. I’ve had a few cases where I’ve returned an object with a zero-length string for the name or customer id or whatever. But in general, if you’re just returning a dummy object so that the caller can test and say, oh, it’s a dummy object, and then throw it away, I think you’re better off to return null.
BTW not sure what you meant when you said that you could only return a null pointer in C++11. The ability to pass around nulls goes back to the earliest version of C++ that I ever saw.