Logan Ding
Logan Ding

Reputation: 1771

Class member initialization failed for singleton mode

I'm writing a class using singleton mode. The code is as below:

A.h

#include <iostream>

class A {
public:
    static A get_instance();
    static A* get_instance_ptr();
    void init(int i);
    void print_data(void);
private:
    static A* instance_ptr;
    int data;
};

A* A::instance_ptr = NULL;

A* A::get_instance_ptr()
{
    if (NULL == instance_ptr) {
        instance_ptr = new A();
    }
    return instance_ptr;
}

A A::get_instance()
{
    return *get_instance_ptr();
}

void A::init(int i) 
{
    data = i;
    std::cout << "In A::init, data = " << data << std::endl;
}

void A::print_data(void)
{
    std::cout << "In A::print_data, data = " << data << std::endl;
}

main.cpp:

#include <iostream>
#include "A.h"

int main(int argc, _TCHAR* argv[])
{
    A::get_instance().init(42);
    A::get_instance().print_data();
    return 0;
}

The principle is to initialize data in A::init() and print it in A::print_data. But the output is:

In A::init, data = 42
In A::print_data, data = 0

It seems the data initialization didn't work. But if I change the initialization in main to:

A::get_instance_ptr()->init(42);

The output is as expected:

In A::init, data = 42
In A::print_data, data = 42

So the question is, why the member initialization failed in the first try?

Upvotes: 0

Views: 141

Answers (1)

Jon
Jon

Reputation: 437336

Because the return type of get_instance is A instead of the correct A& and therefore a copy of your "singleton" is returned each time you call it. The init call operates on a copy of your original object, then print_data operates on a different copy. When all is said and done, main has managed to create three copies of the singleton.

Singletons that can be copied are not really singletons. You should do the bare minimum to prevent copies (declaring private ctors and assignment operator and not defining them).

Upvotes: 2

Related Questions