Advertisement

Return value

Started by November 30, 2014 04:33 PM
16 comments, last by BitMaster 10 years, 2 months ago

Hi,

I am trying to convert a function. Working with pointers, my function is looks like this -

The container-


std::vector<COne*> m_OneContainer;

When I have to find something, I do like this -


COne* CScene::getOneFromId(int id)
{
   for(auto &it: m_OneContainer)
   {
      if((*it)->getID() == id)
      {
         return *it;
      }
   return 0;
}

But when I work with reference -


std::vector<COne> m_OneContainer;

Function -


COne& CScene::getOneFromId(int id)
{
   for(auto &it: m_OneContainer)
   {
      if(it.getID() == id)
      {
         return it;
      }
   return 0; // What do I return here??
}

My question is what do I return as NULL?

Thank you


My question is what do I return as NULL?

You can't. Think of a reference as an alias for an existing object. If so, by definition, a reference can't indicate "non-existent object."

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Advertisement

My question is what do I return as NULL?


You can't. Think of a reference as an alias for an existing object. If so, by definition, a reference can't indicate "non-existent object."

And what you do instead is to throw an exception if no object is found, or you go back to returning a pointer. You can return a pointer to the object in the vector so you don't have to change the vector to store pointers.

Instead of returning the COne instance, you could make a paramter for this and return true if something has been found and false when it does not exist.


bool CScene::getOneFromId(int id, COne &ret)

You need to ask yourself what you expect to happen in your program. Is it expected behavior that sometimes you will not find a "one"? (In which case, return a null pointer, or do something like NLScotty suggests) Or is this like a failure condition indicating a bug in your program? (In which case, assert, or throw an exception).

Anyway, why do you want to convert it from pointers to objects?

I want it to return NULL when it can't find anything. I am trying to avoid using "new" wherever possible. I will stick with my first method for now.

Thank you for the reply.

Advertisement

Pointers are references that can be null. References themselves can't be null*. That's one of the strengths and guarantees* of references.

*Normally. You can cram an address of 0x00 into a reference's memory, but you shouldn't. It defeats the point of using a reference over a pointer.

Some people use a wrapper class called optional<> for that. Boost has an implementation, and C++ will likely get a standard library class like that, but that's still a "maybe" and way off in 2017.

If your object type has some concept of being null, empty, or invalid, you can return a reference to an invalid dummy member variable for invalid returns, but I only recommend you do that if you're returning const references or returning by value.

For example, if the function returns strings or std vectors, you can return an empty string or vector on failure, when it makes sense. But even this isn't the best idea, because you still don't know if the function returned an empty string because of failure, or an empty string because of success.

What I do in this situation, is I pass in the "fallback result" as the final parameter:


const std::string &GetSomething(const std::string &key, const std::string &fallback)
{
     if(...doesn't exist...) return fallback;
 
     return stuff[key];
}

This is for cases where failing to find a result is not considered an error. If it is actually an error, you want the caller to somehow be able to be informed about that, so you should at least be able to pass in an optional boolean pointer to set to true on error.

*Normally. You can cram an address of 0x00 into a reference's memory, but you shouldn't. It defeats the point of using a reference over a pointer.

If you accept undefined behavior, then anything is possible. You cannot have a well defined null-reference.

Can I do like this -


COne* CScene::getOneFromId(int id)
{
   for(auto &it: m_OneContainer)
   {
      if(it.getID() == id)
      {
         COne* one = &it;
         return one;
      }
   }
   return 0;
}

Thank you.

You have to dereference the iterator to get a reference to the object, and then take the address of that reference to get a pointer to the object.

return &*it;

Just taking the address of the iterator will give you a pointer to an iterator to a COne object, but that is not what the function is suppose to return.

This topic is closed to new replies.

Advertisement