Q:

Why doesn't std::shared_ptr dereference throw a null pointer exception (or similar)?

Exceptions are a big part of C++ and one of the reasons to use it (I know there are many, more important, other reasons) is to avoid needless checks that obfuscate code with a lot of if statements (maybe this is an incorrect assumption?).
So now I am curious as to why std::shared_ptr::operator* and std::shared_ptr::operator-> do not throw a null_ptr_exception or similar?

A:

My understanding is that the smart pointer classes are designed to look and behave like raw pointers. Given this guiding design principal, ideally legacy code could simply replace usage of raw pointers with smart pointers using equivalent ownership semantics and the code would work exactly as before.
Therefore, changing the behavior for dereferencing smart pointers should not do any additional checks or throw exceptions (i.e., since raw pointers don't behave this way).
The proposal to add smart pointers to the standard indicates this design decision (A Proposal to Add General Purpose Smart Pointers to the Library Technical Report):

III. Design Decisions
A. General Principles

"As Close to Raw Pointers as Possible, but no Closer"

A:

If every dereference of a shared pointer was required to check for nullptr and conditionally throw an exception, there could be a lot of redundant checks, code bloat and overhead.  Sure - the optimiser's likely to eliminate some of that, but still....  Instead, the programmer's expected to check once before however-many dereferences.

