Returning a "Null Reference" in C++

Returning a NULL reference in C++?

You cannot do this during references, as they should never be NULL. There are basically three options, one using a pointer, the others using value semantics.

  1. With a pointer (note: this requires that the resource doesn't get destructed while the caller has a pointer to it; also make sure the caller knows it doesn't need to delete the object):

    SomeResource* SomeClass::getSomething(std::string name) {
    std::map<std::string, SomeResource>::iterator it = content_.find(name);
    if (it != content_.end())
    return &(*it);
    return NULL;
    }
  2. Using std::pair with a bool to indicate if the item is valid or not (note: requires that SomeResource has an appropriate default constructor and is not expensive to construct):

    std::pair<SomeResource, bool> SomeClass::getSomething(std::string name) {
    std::map<std::string, SomeResource>::iterator it = content_.find(name);
    if (it != content_.end())
    return std::make_pair(*it, true);
    return std::make_pair(SomeResource(), false);
    }
  3. Using boost::optional:

    boost::optional<SomeResource> SomeClass::getSomething(std::string name) {
    std::map<std::string, SomeResource>::iterator it = content_.find(name);
    if (it != content_.end())
    return *it;
    return boost::optional<SomeResource>();
    }

If you want value semantics and have the ability to use Boost, I'd recommend option three. The primary advantage of boost::optional over std::pair is that an unitialized boost::optional value doesn't construct the type its encapsulating. This means it works for types that have no default constructor and saves time/memory for types with a non-trivial default constructor.

I also modified your example so you're not searching the map twice (by reusing the iterator).

How to return Null as reference in C++?

C++ has value semantics. There are nullptrs but there is no null value. A reference always references something. Ergo, there cannot be a reference to null.

Several options you have:

  • throw an exception. Your argument for rejecting them is moot. std::vector::at does exactly that (but I suppose your code is just an example for a more general situation)
  • return a pointer that can be nullptr (not recommended, because then you put the resonsibility on handling it correctly on the caller)
  • return a std::optional. Again this forces the caller to handle the case of "no value returned" but in contrast to returning a nullptr the caller gets a well-designed interface that is hard to use wrong.
  • return an iterator. end is often used to signal "element not found" throughout the standard library, so there will be little surprise if you do the same.
  • perhaps this is not just an example for a different situation, then you should use std::vector::at instead of your handwritten function and be done with it.

P.S. Original task is searching item with property equal to.

You should use std::find to find an item in a container. It returns end of the container when the element cannot be found.

returning NULL pointer in C

NULL is a pointer literal which is defined to contain a special value.

One possible definition is:

#define NULL ((void *)0)

For more detail you can read this faq

About const string& foo(), I believe you mean C++'s std::string.
std::string has no implicit constructor that initialize it with NULL pointer.
So you should use some exception or empty string to indicate an error to the caller. (If you are not throwing, you must return an std::string. Even if the object returned is local, its life is prolonged when kept in a local constant reference. But returning some other type and expecting an implicit conversion is not a good idea.)

Answer to your question: Because NULL is a literal, no temporary object may be created most of the time and actual value can be directly returned to the caller.

Return a NULL object if search result not found

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.)

When is it correct to return a null reference type in C#

Yes you can return null likewise you are currently doing and in which case the responsibility lies to caller to check for nullity before trying to access any of the property of the object. Using C# 6 syntax

muobject?.Age

Per pattern you can use Null Object Pattern; in which case you return an empty object instead of returning null. Thus even if caller mistakes it won't blow up with a NullRefException. For validation purpose you can check for the property value like if(string.IsNullOrEmpty(myobject.name)) ....

C++. How to return null pointer instead of function return type?

Value of return type std::vector<int> cannot be nullptr.

The most straightforward way in this case is to return std::unique_ptr<std::vector<int>> instead - in this case it's possible to return nullptr.

Other options:

  • throw an exception in case of fail
  • use optional<std::vector<int>> as return type (either boost::optional or std::optional if your compiler has this C++17 feature)
  • return bool parameter and have std::vector<int>& as output parameter of function

The best way to go really depends on the use case.
For example, if result vector of size 0 is equivalent to 'fail' - feel free to use this kind of knowledge in your code and just check if return vector is empty to know whether function failed or succeed.

In my practice I almost always stick to return optional (boost or std, depending on environment restriction).
Such interface is the most clear way to state the fact that 'result can either be present or not'.

To sum up - this is not a problem with the only one right solution.
Possible options are listed above - and it's only a matter of your personal experience and environmental restrictions/convetions - which option to choose.

understanding Possible null reference return

It's described in the docs

Returns

The first element that matches the conditions defined by the specified predicate, if found; otherwise, the default value for type T.

So return T? or maybe use ?? for returning a non null value.

About the same signature, in the code you could see this:

[return: MaybeNull]
public T Find(Predicate<T> match)

See the code on github

And the docs for [MaybeNull]

Specifies that an output may be null even if the corresponding type disallows it.

Pointers are NULL after returning from a function

The pointers are passed to the function by values. This means that the function deals with copies of the values of the passed pointers. Changes of the copies do not influence on the original pointers used as argument expressions.

You need to pass them by reference through pointers to them.

For example

Player *upload_players(int *k, int *in_game, int *n_tot, int *k_attivi, 
int** array_indici, int* array_in_game);

and call the function like

players = upload_players(&k, &in_game, &n, &k_attivi, &array_indici, &array_ingame);

Within the function you need to dereference the pointers to get a direct access to the original pointers like for example

*array_indici = calloc(*k_attivi, sizeof(int));

To make it clear compare passing by you pointers and for example the variable k declared in main. The variable k is passed by reference through a pointer to it. Thus changing the variable within the function by dereferencing the pointer to it will be reflected on the original variable k in main. The same way you need to pass the pointers to the function that is by reference through pointers to them.



Related Topics



Leave a reply



Submit