#include <iostream>
#include <memory>
using namespace std;
class Demo {
static shared_ptr<Demo> d;
Demo(){}
public:
static shared_ptr<Demo> getInstance(){
if(!d)
d.reset(new Demo);
return d;
}
~Demo(){
cout << "Object Destroyed " << endl;
}
};
// shared_ptr<Demo> Demo::d(new Demo); // private ctor is accepted
shared_ptr<Demo> Demo::d;
int main()
{
shared_ptr<Demo> d(Demo::getInstance());
cout << d.use_count() << endl;
return 0;
}
This is not thread-safe: two threads calling getInstance
would cause a data race. A common approach is to use a function-scope static variable:
static shared_ptr<Demo> getInstance(){
static shared_ptr<Demo> d(new Demo);
return d;
}
Such a variable is guaranteed to be initialized exactly once, when control passes over its definition for the first time, and in a thread-safe manner.
At this point though, it's not at all clear why you would want to use shared_ptr
. You could just as well do
static Demo& getInstance(){
static Demo d;
return d;
}
This is a textbook implementation of a singleton (well, one of).
Re: initialize with a private constructor. I'm not sure I understand the nature of your confusion. Are you asking why Demo::getInstance
can use private constructor of Demo
? Well, because it's a member of Demo
, and members of a class can access private members of that class. Are you asking why Demo::getInstance
can call shared_ptr<Demo>::reset()
passing a Demo*
pointer? Well, because reset()
is a public member function of shared_ptr
, taking a pointer as a parameter. Which part of this process do you find controversial?
Some comments from 1 to help with the discussion. Static variable will be destroyed uppon exit of the application, so we don't need to use the smart pointer at this stage as mentioned above.
"If multiple threads attempt to initialize the same static local variable concurrently, the initialization occurs exactly once (similar behavior can be obtained for arbitrary functions with std::call_once).
Note: usual implementations of this feature use variants of the double-checked locking pattern, which reduces runtime overhead for already-initialized local statics to a single non-atomic boolean comparison. (since C++11)
The destructor for a block-scope static variable is called at program exit, but only if the initialization took place successfully. "
My 2nd Question above is that how come private constructor called out side of class while instantiating the static member
// shared_ptr<Demo> Demo::d(new Demo); // private ctor is accepted
I think return local static wont work , see below example object destroyed twice
#include <iostream>
using namespace std;
class Demo {
public:
static Demo & getInstance(){
static Demo d;
return d;
}
~Demo(){
cout << "Demo destroyed" << endl;
}
};
void fun(){
Demo l = Demo::getInstance();
}
int main()
{
fun();
cout << "Hello World" << endl;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With