Even though the struct is empty, it has a non zero size. There must be some memory that act as a storage for it.
No. This is always UB. Make it static if you don't need the instance. Static functions are still callable using the dot .
syntax.
Why? Because you cannot dereference a null pointer. Calling a member function equivalent to this:
EmptyStruct *esptr = nullptr;
(*esptr).nonstatic_mf();
As you can see, the null pointer is deferenced, which is UB.
What does the standard says about this? From [class.mfct.non-static]/2:
If a non-static member function of a class X is called for an object that is not of type X, or of a type derived from X, the behavior is undefined.
A null pointer don't point to a valid instance of EmptyStruct
. This alone is enough to make the behaviour undefined
And from [expr.ref]/2:
For the first option (dot) the first expression shall be a glvalue.
For the second option (arrow) the first expression shall be a prvalue having pointer type.
The expression E1->E2
is converted to the equivalent form (*(E1)).E2
; the remainder of [expr.ref] will address only the first option (dot).
So esptr->nonstatic_mf()
is effectively equivalent to (*esptr).nonstatic_mf()
, and derefencing a null pointer is undefined behaviour.
So there's two way in which this code is undefined.