0

Here's my question with sample code. In the case a class function never uses instance related data or never references this, could the compiler decide this function is kind of static ?

As an example see this code (with description below) :

class Dummy
{
    public:
        Dummy()
        {
            std::cout << "Dummy()" << std::endl;
            mInstance = this;
        }
        ~Dummy()
        {
            std::cout << "~Dummy()" << std::endl;
            mInstance = nullptr;
        }

        static Dummy& instance()
        {
            std::cout << "static Dummy& instance()" << std::endl;
            return *mInstance;
        }

        void foo()
        {
            std::cout << "bar" << std::endl;
        }


    private:
        int mData;
        static Dummy* mInstance;


};

Dummy* Dummy::mInstance = nullptr;
  • At construction, my Dummy class references it's instance in a static variable called mInstance using a pointer.
  • mInstance is available through the static function instance().
  • foo() is not a static function. Hence I need and instance to call it.
  • mInstance is initialized to nullptr.

That case if my main only does :

Dummy::instance().foo();

I should get a seg fault. Because instance() would de-reference a nullptr.

Instead the program runs and the output will be :

bar

...And only this line so it does not seem to call neither the constructor nor the destructor.

Yet if my foo() function is :

        void foo()
        {
            mData = 5;
            std::cout << "bar" << std::endl;
        }

Here a seg fault occurs.

I tend to guess as foo() actually did not reference anything proper to the instance, the compiler guessed it was a static and compiled this way. But it does not seem to be logical as instance() function returns a reference to an instance and even if the foo() is static, foo() should not be callable...

As an other example, without the mData = 5 instruction, if my main is :

        Dummy& vDummy = Dummy::instance();
        std::cout << &vDummy << std::endl;
        vDummy.foo();

The output is :

        statci Dummy& instance()
        0
        bar

I don't really understand the way things are done here.... :/

Oragon Efreet
  • 1,114
  • 1
  • 8
  • 25

2 Answers2

3

You can think of member functions (non static) as functions with a hidden parameter that is a pointer to your object. So your void foo() could be considered as void foo(Dummy* d). And since you never use that pointer to Dummy, it does not matter if you pass a NULL pointer to it.

Hope this makes sense :)

For further reading about this type of undefined behaviour: When does invoking a member function on a null instance result in undefined behavior?

Community
  • 1
  • 1
rozina
  • 4,120
  • 27
  • 49
  • Ok thank you. Actually I forgot that undefined behaviour think... What suprised me most was also the dereferencing from nullptr, but that seems logical now :) – Oragon Efreet Apr 10 '14 at 11:47
  • There is no dereferencing from nullptr, because the method isn't virtual. – user207421 Apr 10 '14 at 12:34
1

The reason for this behaviour is that 'foo()' isn't virtual, so the object it's being called on is only used for type information at compile time. At runtime the fact that it's null has no effect, unless you used 'this' inside 'foo()', when you would get a nasty surprise, as you did when you tried to set a member variable, which uses 'this' implicitly.

user207421
  • 305,947
  • 44
  • 307
  • 483