1

I have been trying to implement a singleton class in C++.

#include<iostream>
using namespace std;

class Singleton {
private:
static Singleton* singleton;
public:
static Singleton& Get() {
    return *singleton;
}
static void display() {
    cout << "Hello world\n";
}
};

Singleton* Singleton::singleton = nullptr;
int main() {
Singleton::Get().display();
return 0 ;
}

the program works fine. Can anyone please help me understand how dereferencing a nullptr, is giving back the object reference in 'Get' function of the class.

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
  • 2
    It probably seems to work because `display` is *also* a static member function. It's still [*undefined behavior*](https://en.wikipedia.org/wiki/Undefined_behavior) though, since you're dereferencing a null pointer. Unfortunately, one of the possibilities of UB is that things *seems* to work. – Some programmer dude Nov 04 '18 at 16:25
  • 1
    Unrelated: [A better way to write a singleton](https://stackoverflow.com/a/1008289/4581301). – user4581301 Nov 04 '18 at 16:31
  • Even after making 'display' non-static , the program works. – aman shrivastava Nov 04 '18 at 16:32
  • 1
    The given code does not check whether any object is correct. Actually C++ provides no means to perform such a check. It is always a programmer's responsibility to ensure that objects being used are in valid state. – user7860670 Nov 04 '18 at 16:57

2 Answers2

4

This is covered by core language issue 315: Is call of static member function through null pointer undefined? which says:

Another instance to consider is that of invoking a member function from a null pointer:

  struct A { void f () { } };
  int main ()
  {
    A* ap = 0;
    ap->f ();
  }

Which is explicitly noted as undefined in 12.2.2 [class.mfct.non-static], even though one could argue that since f() is empty, there is no lvalue->rvalue conversion.

If f is static, however, there seems to be no such rule, and the call is only undefined if the dereference implicit in the -> operator is undefined. IMO it should be.

Incidentally, another thing that ought to be cleaned up is the inconsistent use of "indirection" and "dereference". We should pick one. (This terminology issue has been broken out as issue 342.)

This is related to issue 232.

and the response was:

We agreed the example should be allowed. p->f() is rewritten as (*p).f() according to 8.2.5 [expr.ref]. *p is not an error when p is null unless the lvalue is converted to an rvalue (7.1 [conv.lval]), which it isn't here.

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
0

Basically, that's because everything in Singleton is static. Add a data element and do something with it and you'll be more likely to see problems.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165