I have a function and call it:
Class1& Class2::get()
{
return *m_ptr;
}
Class1& c = m_class2->get();
m_ptr is a custom smart pointer and I can see in debugger that m_ptr.m_p is 0, also I can see inside its operator T* that it really returns 0. However address of c (&c) is not NULL, it is 0x30! What I see in disassembly:
13059 return *m_ptr;
eaabbc7e: mov 0x8(%ebp),%eax
eaabbc81: add $0xb4,%eax
eaabbc86: mov %eax,(%esp)
eaabbc89: call 0xea9ce4c0 <operator T*>
eaabbc8e: add $0x30,%eax
13060 }
Just before line add $0x30,%eax I can see that %eax is 0, that is operator correctly returned NULL.
Why the line to add 0x30 is here???
Although there’s not enough information to answer, your comments hint that
Class2involves multiple inheritance, and I will hazard a guess that the template parameterTa derived class, notClass2itself.So
operator T*returns a pointer to this derived class. In order to dereference it to giveClass2&, it must be converted toClass2*, which may involve adding an offset to the pointer, depending on how the compiler lays out the base class sub-objects within the object.Obviously this is only valid if the pointer is not null; that’s one reason why you must never dereference a null pointer even if you’re only using the result to initialise a reference.
If the function returned
Class2*, then you would get a null pointer as expected; that conversion is required to convert null to null. In your case, since you’re invoking undefined behaviour in that case by dereferencing the pointer, there’s no need for the compiler to check for null before performing the conversion.