Returns a NULL object if no search result is found

I am new to C ++, so I try to develop many Java isms during training. In any case, in Java, if I had a class with a search method that would return a T object from Collection< T > that matched a specific parameter, I would return that object and if the object was not found in the collection, I will return null . Then in my calling function I would just check if(tResult != null) { ... }

In C ++, I find that I cannot return null if the object does not exist. I just want to return an “indicator” of type T, which notifies the calling function that the object was not found. I do not want to throw an exception, because this is not an exceptional circumstance.

Here's 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 that I can specify this marker?

+80
c ++ return-value sentinel
Apr 14 '10 at 16:41
source share
8 answers

In C ++, links cannot be empty. If you want to optionally return null, if nothing is found, you need to return a pointer, not a link:

 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, you should throw an exception if the attribute is not found.

(By the way, I'm a little worried that your method returns a const attribute. For philosophical reasons, I suggest returning const Attr * . If you also want to change this attribute, you can overload using the const method, which returns an attribute not const .)

+56
Apr 14 '10 at 16:44
source share

There are several possible answers. You want to return something that could exist. Here are a few options, starting from my least preferred and most preferred:

  • Return by reference, and the signal cannot be found 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 is likely that attribute search is not a normal part of execution and therefore not very exclusive. Handling this would be noisy. A null value cannot be returned because its undefined behavior has null references.

  • Return 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 if the result of getAttribute is not a NULL pointer and is an easy source of errors.

  • 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 means what happens here, and has simple methods for checking whether such an attribute was found.




Side note: std :: optional was recently voted for C ++ 17, so this will be a “standard” thing in the near future.

+47
Apr 14 '10 at 16:57
source share

You can easily create a static object that represents a NULL return.

 class Attr; extern Attr AttrNull; class Node { .... Attr& getAttribute(const string& attribute_name) const { //search collection //if found at i return attributes[i]; //if not found return AttrNull; } bool IsNull(const Attr& test) const { return &test == &AttrNull; } private: vector<Attr> attributes; }; 

And somewhere in the source file:

 static Attr AttrNull; 
+22
Apr 14 2018-10-14T00:
source share

If you want to return NULL , you need to use pointers instead of references.

Links by themselves cannot be NULL .

(Note to posters of future commentary: Yes, you can specify the address of the NULL link if you are really trying).

See my answer here for a list of differences between links and pointers .

+3
Apr 14 '10 at 16:44
source share

As you understand, you cannot do it the way you did in Java (or C #). Here is another suggestion, you can pass an object reference as an argument and return a bool value. If the result is found in your collection, you can assign it to the transmitted link and return "true", otherwise return "false". Please review this code.

 typedef std::map<string, Operator> OPERATORS_MAP; bool OperatorList::tryGetOperator(string token, Operator& op) { bool val = false; OPERATORS_MAP::iterator it = m_operators.find(token); if (it != m_operators.end()) { op = it->second; val = true; } return val; } 

The above function should find the Operator against the token key if it finds one that returns true and assigns a value to the Operator & op parameter.

The caller code for this procedure is as follows:

 Operator opr; if (OperatorList::tryGetOperator(strOperator, opr)) { //Do something here if true is returned. } 
+2
Feb 20 '16 at 13:22
source share

The reason you cannot return NULL is because you specified your return type as Attr& . The final & makes the return value a "reference", which is basically a pointer to a guaranteed-non-null value for an existing object. If you want to return null, change Attr& to Attr* .

+1
Apr 14 2018-10-14T00:
source share

You cannot return NULL because the return type of the function is a reference object, not a pointer .

0
Apr 14 '10 at 16:45
source share

You can try the following:

 return &Type(); 
-four
Dec 14 '15 at 21:08
source share



All Articles