sameer
sameer

Reputation: 81

simple singleton example in c++

I am trying to implement singleton that I have used before in PHP and Java 8, to C++. But I do face certain restrictions from the syntax and how C++ works (specifically pointers).

This is what I have tried so far:

#include "iostream"

using namespace std;

class System{
protected:
    static System *obj;

public:
    static System *getInstance(){
        return obj;
    }

    void prn(){
        cout<<"this works!";
    }
};

int main(void){
    System &sys = System::getInstance();
    sys.prn();
}

while executing, I get the following error:

 sameer.cpp:20:10: error: non-const lvalue reference to type 'System'
 cannot bind
       to a temporary of type 'System *'
         System &sys = System::getInstance();
                 ^     ~~~~~~~~~~~~~~~~~~~~~

Please help me solve this error.. as I have no idea what it means. I have checked the forum before posting, and it can be a possible duplicate of previously asked question (which I caould not find).. But I posted this because I wanted to understand the meaning of error my code generated.

Thanks for the help

Upvotes: 3

Views: 27691

Answers (4)

AlexG
AlexG

Reputation: 1103

It might be good to lazy-initialize your singleton. Also, consider making the constructor and the singleton private so you can't create an instance anywhere else.

#include <iostream>

class System
{
private:
    static System *obj;
    System() {}
    
public:
    static System& getInstance(){
        if (nullptr == obj)
            obj = new System();

        return obj;
    }
    
    void prn(){
        std::cout << "this works!";
    }
};

int main(void){
    System& sys = System::getInstance();
    sys.prn();
}

Upvotes: -1

Ravi
Ravi

Reputation: 59

#include <iostream>
using namespace std;

class System{
private:
    static System *obj;
    System() {}

public:
    static System *getInstance()
    {
        if(obj == nullptr)
            obj = new System();
        return obj;
    }

    void prn(){
        cout<<"this works!"<< endl;
    }
};

System *System::obj;

int main(void){
    System *sys = System::getInstance();
    sys->prn();
}

Upvotes: 3

Tristan Brindle
Tristan Brindle

Reputation: 16824

In C++, references and pointers are different things. A reference behaves exactly like the original variable, whereas a pointer represents the memory address of that variable. You're getting the error because you're trying to assign a pointer-to-System to a variable of type reference-to-System, which isn't the same thing. If you really wanted to you could dereference the pointer by using the System& sys = *ptr; syntax, but in this case that's the wrong thing to do; the correct fix is to return a reference from your getInstance() function, rather than a pointer.

What's more, in C++ you can actually store the static instance variable within the getInstance() function. This is a so-called "magic static", otherwise known as a "Meyers Singleton", and since C++11 it guarantees you get thread-safe construction of the singleton object. So the final solution would be:

class System
{
private:
    System() {}

public:
    static System& getInstance(){
        static System theInstance;
        return theInstance;
    }

    void prn(){
        cout<<"this works!";
    }
};

int main()
{
    System& sys = System::getInstance();
    sys.prn();
}

Also, as an aside, you should use

#include <iostream>

not

#include "iostream"

to include standard library headers. And you don't need to say main(void) in C++; empty brackets signify that a function takes no arguments, so main() will do.

Upvotes: 17

aschepler
aschepler

Reputation: 72271

getInstance() returns a pointer, but you are trying to call it and bind it to a reference. If you want it to return a reference, make it return a reference.

static System &getInstance(){
    return *obj;
}

Upvotes: 2

Related Questions