Empty class & null pointers

If a class is empty, is it safe, or is it undefined, to cast to it from a nullptr and call member functions?

EDIT: This is my 9333th post, makes me think of naraku9333
Last edited on
According to the top answer here http://stackoverflow.com/questions/11320822/why-does-calling-method-through-null-pointer-work-in-c it's legal.
According to answers here http://stackoverflow.com/questions/2505328/calling-class-method-through-null-class-pointer it's undefined behavior.
I'm feel more inclined to believe the latter. I can't find a reference in the standard stating either way.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
struct empty
{
    void foo() const ;
    // ...
};

void bar( empty* e )
{
    if( e ) e->foo() ;
    else empty{}.foo() ; // this is fine

    e->foo() ; // undefined behaviour if e is null
}

void empty::foo() const
{
    empty temp = *this ;
    // ...
}
Is line 17 supposed to be scary? I don't see how that could have bad results (other than UB).

I guess I'm overly hopeful that the standard makes some weird exception for empty classes. I mean, it's not like there's any data to access...
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
extern "C" int printf(const char *,...);

class a_class
{
  public:
    void mem_func();
};

void a_class::mem_func()
{
  printf("\nIn empty::mem_func");
}

int main()
{
  a_class *ac_ptr = 0L;
  ac_ptr->mem_func();
  return 0;
}


Consider only this part of code for simplicity:

1
2
3
4
5
6
7
void a_class::mem_func()
{
  printf("\nIn empty::mem_func");
}

a_class *ac_ptr = 0L;
ac_ptr->mem_func();


Internally(code generated by compiler) this becomes:

1
2
3
4
5
6
7
void _ZN7a_class8mem_funcEv( struct a_class *const this)
{
  printf(((const char *)"\nIn empty::mem_func"));
}
  
auto struct a_class *ac_ptr = ((struct a_class *)0);
_ZN7a_class8mem_funcEv(ac_ptr);


So as far as this pointer (struct a_class *const this) is not used inside member function a_class::mem_func (mangled as _ZN7a_class8mem_funcEv) this code will work (provided the compiler generates such code. Most (all that I know of) of the compiler choose to implement member function call as shown above.)


@7 void bar( empty* e )
@8 {
@12 e->foo() ; // undefined behaviour if e is null
@15 void empty::foo() const
@16 {
@17 empty temp = *this ;

Is line 17 supposed to be scary? I don't see how that could have bad results (other than UB).

For sure it is a null pointer dereference (provided the "this" pointer is null).
So it is scary and a undefined behaviour too.

Snip from Standard ISO/IEC 9899:1999 C:

6.5.3.3 footer note "Among the invalid values for de-referencing 
a pointer by the unary * operator are a null pointer"
> So as far as this pointer is not used inside member function
if the state of the object is not modified or used, then it shouldn't be a member function.
If a class is empty, is it safe, or is it undefined, to cast to it from a nullptr and call member functions?
It is safe. The pointer is passed to the function. If you don't use the this pointer there's no reason that anything could possibly go wrong.

It sounds very much like a design fault though
> if the state of the object is not modified or used, then it shouldn't be a member function.

The canonical counter example is a stateless function object; for instance std::less<>

Other examples are types that encapsulate policy: stateless allocators a la std::allocator<>, traits classes like (std::char_traits<>) etc.
If a class is empty, is it safe, or is it undefined, to cast to it from a nullptr and call member functions?

Yes, it is safe...A null pointer is a regular pointer of any pointer type which has a special value that indicates that it is not pointing to any valid reference or memory address. This value is the result of type-casting the integer value zero to any pointer type.
JLBorges hit the snail on the head. I was just curious if there was an easier way than doing some convoluted stuff with a static global instance. This thread is a spin-off of Catfish's thread.
Topic archived. No new replies allowed.