Return a "NULL" object if search result not found
I'm pretty new to C++ so I tend to design with a lot of Java-isms while I'm learning. Anyway, in Java, if I had class with a 'search' method that would return an object T
from a Collection< T >
that matched a specific parameter, I would return that object and if the object was not found in the collection, I would return null
. Then in my calling function I would just check if(tResult != null) { ... }
In C++, I'm finding out that I can't return a null
value if the object doesn't exist. I just want to return an 'indicator' of type T that notifies the calling function that no object has been found. I don't want to throw an exception because it's not really an exceptional circumstance.
This is what my code looks like right now:
class Node {
Attr& getAttribute(const string& attribute_name) const {
//search collection
//if found at i
return attributes[i];
//if not found
return NULL; // what should this be?
}
private:
vector<Attr> attributes;
}
How can I change it so I can give that kind of marker?
In C++, references can't be null. If you want to optionally return null if nothing is found, you need to return a pointer, not a reference:
Attr *getAttribute(const string& attribute_name) const {
//search collection
//if found at i
return &attributes[i];
//if not found
return nullptr;
}
Otherwise, if you insist on returning by reference, then you should throw an exception if the attribute isn't found.
(By the way, I'm a little worried about your method being const
and returning a non-const
attribute. For philosophical reasons, I'd suggest returning const Attr *
. If you also may want to modify this attribute, you can overload with a non-const
method returning a non-const
attribute as well.)
There are several possible answers here. You want to return something that might exist. Here are some options, ranging from my least preferred to most preferred:
-
Return by reference, and signal can-not-find by exception.
Attr& getAttribute(const string& attribute_name) const { //search collection //if found at i return attributes[i]; //if not found throw no_such_attribute_error; }
It's likely that not finding attributes is a normal part of execution, and hence not very exceptional. The handling for this would be noisy. A null value cannot be returned because it's undefined behaviour to have null references.
-
Return by pointer
Attr* getAttribute(const string& attribute_name) const { //search collection //if found at i return &attributes[i]; //if not found return nullptr; }
It's easy to forget to check whether a result from getAttribute would be a non-NULL pointer, and is an easy source of bugs.
-
Use Boost.Optional
boost::optional<Attr&> getAttribute(const string& attribute_name) const { //search collection //if found at i return attributes[i]; //if not found return boost::optional<Attr&>(); }
A boost::optional signifies exactly what is going on here, and has easy methods for inspecting whether such an attribute was found.
Side note: std::optional was recently voted into C++17, so this will be a "standard" thing in the near future.