> if the function returns null?
What does 'null' mean in this context?
If the function returns
void, we can't use references at all; void is not an
object-type.
void foo() ; const auto& v = foo() ; // *** error: cannot form a reference to 'void'
If the function returns a pointer, we can initialise a references with it; a pointer is an
object-type.
int* bar() ; const int*& p = bar() ; // fine: but p may me referring to a nullptr
In this case, you may want to check if
p == nullptr.
With incorrectly written functions like these
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
struct my_type { /* ... */ };
const my_type& my_bad_func()
{
my_type m ;
return m ; // this is wrong. a diagnostic may be generated
// *** warning: reference to local variable 'm' returned
}
const my_type& my_worse_func()
{
my_type* p = nullptr ;
return *p ; // this too is wrong. though a diagnostic may not be generated
}
|
there is really nothing much that the calling code can do.
Other than something like:
1 2 3 4
|
const auto& ref = my_worse_func() ;
assert( std::addressof(ref) != nullptr ) ;
if( std::addressof(ref) == nullptr )
throw std::logic_error( "my_worse_func engendered undefined behaviour" ) ;
|
Even that is not guaranteed to work (though it usually does); the undefined behaviour had occurred earlier.
What can we do to catch programming errors?
Write idiomatic C++ code.
Strongly favour using the standard library over home-grown solutions.
Identify invariants and assert them in the code.
Turn on all compiler warnings, and pay attention to them.
A compiler can't be expected to catch all mistakes; so:
Compile with more than one compiler. If possible, run one or more static-code-analysis tools.
Subject the code to a formal peer-review.
Even if all this is done, there may be errors that are not detected.
So test the code: as early, as thoroughly, and as often as possible.
That is the best we can do; minimise the probability of undetected errors.
Rest with the knowledge that an undetected error may still be lurking in the released code.