Is this possible?
class A {
static A *instance = NULL;
public:
A () {
if (instance) {
this = instance;
} else {
instance = this;
}
}
}
Does it have leak memory?
Do I need to oveload new operator?
No. Overlooking your compiler errors, your class won't work.
#Galik has provided invaluable sources for how you'd actually want to construct a singleton. But let's look at yours.
class A {
static A *instance = NULL; // NULL isn't even a thing, but assuming you mean nullptr you can't assign a static like this
public:
A () {
if (instance) {
this = instance; // this can't be assigned
} else {
instance = this; // this is correct
}
}
};
Which would give you the following:
class A {
static A *instance;
public:
A () {
// if there's no instance, this is the one we'll use
if (!instance) {
instance = this;
}
}
};
A* A::instance = nullptr;
Which doesn't stop you from constructing more than one anyway.
Not possible. If the constructor is exposed and called, a new object of A is inevitably created. The most elegant and widely used implementations of C++ singleton classes use static methods to return the single static instance, while hiding (e.g. make private accessible) the constructor.
Here's an example:
class A {
private:
static A *instance_; // use nullptr since C++11
A() {}
public:
static A& instance() {
if (!instance_)
instance_ = new A();
return *instance_;
}
};
A* A::instance_ = nullptr;
You cannot assign a value for this
Related
I have a singleton class with a private constructor. In the static factory method I do the following:
shared_ptr<MyClass> MyClass::GetInstance()
{
static once_flag onceFlag;
call_once(onceFlag, []() {
if (_instance == nullptr)
_instance.reset(new MyClass());
});
return _instance;
}
If I use
_instance = make_shared<MyClass>();
the code does not compile. My question is: why new can invoke a private constructor but make_shared not?
As mentioned, std::make_shared or its component parts don't have access to private members.
the call_once and once_flag are un-necessary. They are implicit in c++11 static initialisation,
You normally would not want to expose the shared pointer.
class MyClass
{
MyClass() {}
public:
static MyClass& GetInstance()
{
static auto instance = MyClass();
return instance;
}
};
However, there is one case I can imagine where you would want to expose a shared pointer to the impl - this is in the case where the class can choose to 'break off' or 'reset' the impl to a new one. In this case I would consider code like this:
class MyClass2
{
MyClass2() {};
static auto& InternalGetInstance()
{
static std::shared_ptr<MyClass2> instance { new MyClass2 };
return instance;
}
public:
static std::shared_ptr<MyClass2> GetInstance()
{
return std::atomic_load(std::addressof(InternalGetInstance()));
}
static void reset() {
std::atomic_store(std::addressof(InternalGetInstance()),
std::shared_ptr<MyClass2>(new MyClass2));
}
};
However, in the end, it is my view that 'staticness' of a class should be an implementation detail, and unimportant to the user of the class:
#include <memory>
#include <utility>
class MyClass
{
// internal mechanics
struct Impl {
auto doSomething() {
// actual implementation here.
}
};
// getImpl now becomes the customisation point if you wish to change the
// bahviour of the class later
static Impl& getImpl() {
static auto impl = Impl();
return impl;
}
// use value semantics - it makes for more readable and loosely-coupled code
public:
MyClass() {}
// public methods defer to internal implementation
auto doSomething() {
return getImpl().doSomething();
}
};
int main() {
// note: just create objects
auto mc = MyClass();
mc.doSomething();
// now we can pass the singleton as an object. Other functions don't even
// need to know it's a singlton:
extern void somethingElse(MyClass mc);
somethingElse(mc);
}
void somethingElse(MyClass mc)
{
}
Please take VTT's comment seriously.
To your question:
My question is: why new can invoke a private constructor but make_shared not?
The new is actually used within a lambda in a member-function; Well, A lambda defines a local-class, and C++ standards permits a local-class within a member-function to access everything the member-function can access. And its trivial to remember that member functions can access privates..
std::make_shared has no access to the privates of MyClass. It's outside the scope of MyClass
Example:
class X{
X(){};
public:
static X* create(){ // This member-function can access private functions and ctors/dtor
auto lm = [](){ // This lambda inherits the same access of enclosing member-function
return new X();
};
return lm();
}
};
int main(){
auto x = X::create(); //valid;
auto y = new X(); //invalid;
}
You should use Meyers singleton instead. You should ensure that your compiler supports C++11 magic static before.
I have a singleton class with a private constructor. In the static factory method I do the following:
shared_ptr<MyClass> MyClass::GetInstance()
{
static once_flag onceFlag;
call_once(onceFlag, []() {
if (_instance == nullptr)
_instance.reset(new MyClass());
});
return _instance;
}
If I use
_instance = make_shared<MyClass>();
the code does not compile. My question is: why new can invoke a private constructor but make_shared not?
As mentioned, std::make_shared or its component parts don't have access to private members.
the call_once and once_flag are un-necessary. They are implicit in c++11 static initialisation,
You normally would not want to expose the shared pointer.
class MyClass
{
MyClass() {}
public:
static MyClass& GetInstance()
{
static auto instance = MyClass();
return instance;
}
};
However, there is one case I can imagine where you would want to expose a shared pointer to the impl - this is in the case where the class can choose to 'break off' or 'reset' the impl to a new one. In this case I would consider code like this:
class MyClass2
{
MyClass2() {};
static auto& InternalGetInstance()
{
static std::shared_ptr<MyClass2> instance { new MyClass2 };
return instance;
}
public:
static std::shared_ptr<MyClass2> GetInstance()
{
return std::atomic_load(std::addressof(InternalGetInstance()));
}
static void reset() {
std::atomic_store(std::addressof(InternalGetInstance()),
std::shared_ptr<MyClass2>(new MyClass2));
}
};
However, in the end, it is my view that 'staticness' of a class should be an implementation detail, and unimportant to the user of the class:
#include <memory>
#include <utility>
class MyClass
{
// internal mechanics
struct Impl {
auto doSomething() {
// actual implementation here.
}
};
// getImpl now becomes the customisation point if you wish to change the
// bahviour of the class later
static Impl& getImpl() {
static auto impl = Impl();
return impl;
}
// use value semantics - it makes for more readable and loosely-coupled code
public:
MyClass() {}
// public methods defer to internal implementation
auto doSomething() {
return getImpl().doSomething();
}
};
int main() {
// note: just create objects
auto mc = MyClass();
mc.doSomething();
// now we can pass the singleton as an object. Other functions don't even
// need to know it's a singlton:
extern void somethingElse(MyClass mc);
somethingElse(mc);
}
void somethingElse(MyClass mc)
{
}
Please take VTT's comment seriously.
To your question:
My question is: why new can invoke a private constructor but make_shared not?
The new is actually used within a lambda in a member-function; Well, A lambda defines a local-class, and C++ standards permits a local-class within a member-function to access everything the member-function can access. And its trivial to remember that member functions can access privates..
std::make_shared has no access to the privates of MyClass. It's outside the scope of MyClass
Example:
class X{
X(){};
public:
static X* create(){ // This member-function can access private functions and ctors/dtor
auto lm = [](){ // This lambda inherits the same access of enclosing member-function
return new X();
};
return lm();
}
};
int main(){
auto x = X::create(); //valid;
auto y = new X(); //invalid;
}
You should use Meyers singleton instead. You should ensure that your compiler supports C++11 magic static before.
Is there any difference or specific advice when it comes to the following approaches for defining singletons?
In 1, the singleton object is a class private static, but in 2, it's a file static.
Note: m_initedObj1 is just there to show that class has state, and use case is to call this singleton->DoSomething() many times, without needing to init this object again.
1)
// header file
class Foo {
private:
static Foo* s_fooSingleton;
Foo();
Obj1 m_initedObj1;
public:
static Foo* Singleton();
static void ClearSingleton();
Bar DoSomething(...);
};
// cpp file
Foo* Foo::s_fooSingleton = nullptr;
Foo::Foo() { m_initedObj1 = InitObj1Somewhere(); }
/*static*/ Foo* Foo::Singleton()
{
if(!Foo::s_fooSingleton)
Foo::s_fooSingleton = new Foo();
return Foo::s_fooSingleton;
}
/*static*/ void Foo::ClearSingleton()
{
if(Foo::s_fooSingleton)
delete Foo::s_fooSingleton;
Foo::s_fooSingleton = nullptr;
}
Bar Foo::DoSomething(...) { // do something }
2)
// header file
class Foo {
private:
Foo();
Obj1 m_initedObj1;
public:
static Foo* Singleton();
static void ClearSingleton();
Bar DoSomething(...);
};
// cpp file
static Foo* s_fooSingleton = nullptr;
Foo::Foo() { m_initedObj1 = InitObj1Somewhere(); }
/*static*/ Foo* Foo::Singleton()
{
if(!s_fooSingleton)
s_fooSingleton = new Foo();
return s_fooSingleton;
}
/*static*/ void Foo::ClearSingleton()
{
if(s_fooSingleton)
delete s_fooSingleton;
s_fooSingleton = nullptr;
}
Bar Foo::DoSomething(...) { // do something }
As JerryGoyal states in the comments, in 2) other methods in the same .cpp file can modify s_fooSingleton.
On the other hand, they are not both thread-safe. If you don't really mind the clearing (calling ClearSingleton() explicitly), just go with the Scott Meyers' version. Otherwise, go with the double checked locking version.
It's really hard to ensure the safety in case of explicitly deleting. You always have to check whether it's deleted before you access it. If it's a multi-threaded executable, checking and using it must be atomic, because it can be deleted just after checking.
Double checked locking could be used to create and delete the singleton, which ensures you that there is only one instance at a time. Yet, it does not ensure the object really exist, since you may accidentally delete it.
You may use smart pointers to count references and delete it if no references exist.
Or even better, see this answer https://stackoverflow.com/a/15733545/1632887.
I just wouldn't delete it explicitly if I were you!
Maybe this will satisfy you more:
class MyClass1 {
private:
MyClass1(){}
public:
MyClass1& Instance() {
static MyClass1 theSingleInstance;
return theSingleInstance;
}
};
class MyClass2 {
private:
MyClass2() {}
public:
MyClass2* Instance() {
static MyClass2* theSingleInstance = new MyClass2;
return theSingleInstance;
}
};
class MyClass3 {
private:
MyClass3() {}
public:
MyClass3* Instance() {
static MyClass3 theSingleInstance;
return &theSingleInstance;
}
};
I have a singleton with a following structure:
// Hpp
class Root : public boost::noncopyable
{
public:
~Root();
static Root &Get();
void Initialize();
void Deinitialize();
private:
Root(); // Private for singleton purposes
static boost::scoped_ptr<Root> mInstance;
Manager1 *mManager1;
Manager2 *mManager2;
};
// Cpp
boost::scoped_ptr<Root> Root::mInstance;
Root::Root()
{
// [!!!]
mInstance = this;
// Managers are using `mInstance` in their constructors
mManager1 = new Manager1();
mManager2 = new Manager2();
mInstance->Initialize();
}
Root::~Root() { delete mManager1; delete mManager2; }
Root &Root::Get()
{
if (mInstance == nullptr) mInstance = boost::scoped_ptr<Root>(new Root());
return *mInstance;
}
The idea is to remove instance automatically when program exists. Look at line marked [!!!] : mInstance = this. I have to do this because mManager1 and mManager2 are using mInstance in their purposes in ctor.
The problem is how to use this with boost::scoped_ptr? In shared_ptr case there is enable_shared_from_this class from boost which allows to get what I need. But what to do in my case?
You can simply have the constructors take the Root as argument, and then pass this to them:
Root::Root() {
mManager1 = new Manager1(this);
mManager2 = new Manager2(this);
Initialize();
}
One additional advantage of this is that you don't get the other classes coupled to the singleton secretly.
I am trying to create a static member function that returns a pointer to one instance of the class. Is this possible in C++?
class DynamicMemoryLog
{
// Singleton Class:
public:
static DynamicMemoryLog* CreateLog();
void AddIObject( IUnknown* obj );
void ReleaseDynamicMemory();
private:
// static DynamicMemoryLog* instance;
static bool isAlive; // used to determine is an instance of DynamicMemoryLog already exists
DynamicMemoryLog();
~DynamicMemoryLog();
std::vector <IUnknown*> iObjectList;
};
This function below should create a new instance of the class & return a pointer to that object, but the compiler will not allow me to define a static function of the class if it returns a pointer(I think thats why it wont compile?):
static DynamicMemoryLog* DynamicMemoryLog :: CreateLog()
{
// Post:
if ( !isAlive ) // ( instance == NULL; )
{
DynamicMemoryLog* instance = new DynamicMemoryLog();
return instance;
}
return NULL;
}
The particular error you're getting is that when implementing a static member function, you don't repeat the static keyword. Fixing this should resolve the error.
Independently, there's something a bit odd with your code. You claim that this object is a singleton, but each call to CreateLog will create a new instance of the class. Do you really want this behavior, or do you want there to be many copies? I'd suggest looking into this before proceeding.
Here's the simplest solution, but not thread-safe. For analysis in detail, have a look at this article.
class DynamicMemoryLog
{
public:
static DynamicMemoryLog* GetInstance();
private:
DynamicMemoryLog();
static DynamicMemoryLog* m_pInstance;
}
DynamicMemoryLog* DynamicMemoryLog::GetInstance()
{
if(!m_pInstance)
{
m_pInstance = new DynamicMemoryLog();
}
return m_pInstance;
}
I usually do something like this:
class Singleton
{
public:
static Singleton* get()
{
static Singleton instance;
return &instance;
}
};
This way you won't have any nasty memory management issues.