Definition: the single-piece mode ensures that a class has only one instance and provides a global access point.
Implementation 1:
#include <iostream>
using namespace std;
class CSingleton
{
public:
static CSingleton* getInstance();
static void cleanInstance();
int getValue();
void setValue(int iValue);
private:
int m_iValue;
static CSingleton* m_pSingleton;
CSingleton();
~CSingleton();
};
CSingleton* CSingleton::m_pSingleton = NULL;
CSingleton::CSingleton()
{
cout << "Constructor" << endl;
}
CSingleton::~CSingleton()
{
cout << "Destructor" << endl;
}
CSingleton* CSingleton::getInstance()
{
if (NULL == m_pSingleton)
{
m_pSingleton = new CSingleton();
}
return m_pSingleton;
}
void CSingleton::cleanInstance()
{
delete m_pSingleton;
}
int CSingleton::getValue()
{
return m_iValue;
}
void CSingleton::setValue(int iValue)
{
m_iValue = iValue;
}
int main()
{
CSingleton* pSingleton1 = CSingleton::getInstance();
CSingleton* pSingleton2 = CSingleton::getInstance();
pSingleton1->setValue(123);
if (pSingleton1->getValue() == pSingleton2->getValue())
{
cout << "Two objects is the same instance" << endl;
}
else
{
cout << "Two objects isn't the same instance" << endl;
}
CSingleton::cleanInstance();
return 0;
}
I believe that most of my colleagues like to use the single-piece mode above. If it is a single thread, it is okay, but if it is a multi-thread, then it is very likely that two different objects will be returned.
Csingleton: When getinstance is used, if both threads run the if Statement at the same time, but the constructor has not been called yet, imagine the consequences. What should we do? See the implementation below.
Implementation 2:
# Include <iostream>
Using namespace STD;
Class csingleton
{
Public:
Static csingleton * getinstance ();
Static void cleaninstance ();
Int getvalue ();
Void setvalue (INT ivalue );
PRIVATE:
Int m_ivalue;
Static csingleton * m_psingleton;
Csingleton ();
~ Csingleton ();
};
// This single piece is instantiated when the process starts to run, also known as "eager" to create an instance
Csingleton * csingleton: m_psingleton = new csingleton ();
Csingleton: csingleton ()
{
Cout <"constructor" <Endl;
}
Csingleton ::~ Csingleton ()
{
Cout <"destructor" <Endl;
}
Csingleton * csingleton: getinstance ()
{
Return m_psingleton;
}
Void csingleton: cleaninstance ()
{
Delete m_psingleton;
}
Int csingleton: getvalue ()
{
Return m_ivalue;
}
Void csingleton: setvalue (INT ivalue)
{
M_ivalue = ivalue;
}
Int main ()
{
Csingleton * psingleton1 = csingleton: getinstance ();
Csingleton * psingleton2 = csingleton: getinstance ();
Psingleton1-& gt; setvalue (123 );
If (psingleton1-> getvalue () = psingleton2-> getvalue ())
{
Cout <"two objects is the same instance" <Endl;
}
Else
{
Cout <"two objects isn' t the same instance" <Endl;
}
Csingleton: cleaninstance ();
Return 0;
}
Haha, are you clear? The single piece is instantiated when the process is running, but it does not seem to be able to achieve the purpose of delayed instantiation. It would be a waste of resources if our objects occupy a large amount of resources and we do not use this single item during the whole process. There is a better way.
Implementation 3:
#include <iostream>
using namespace std;
class CSingleton
{
public:
static CSingleton* getInstance();
int getValue();
void setValue(int iValue);
private:
int m_iValue;
CSingleton();
~CSingleton();
};
CSingleton::CSingleton()
{
cout << "Constructor" << endl;
}
CSingleton::~CSingleton()
{
cout << "Destructor" << endl;
}
CSingleton* CSingleton::getInstance()
{
static CSingleton single;
return &single;
}
int CSingleton::getValue()
{
return m_iValue;
}
void CSingleton::setValue(int iValue)
{
m_iValue = iValue;
}
int main()
{
cout << "Process begin" << endl;
CSingleton* pSingleton1 = CSingleton::getInstance();
CSingleton* pSingleton2 = CSingleton::getInstance();
pSingleton1->setValue(123);
if (pSingleton1->getValue() == pSingleton2->getValue())
{
cout << "Two objects is the same instance" << endl;
}
else
{
cout << "Two objects isn't the same instance" << endl;
}
return 0;
}
Check the running result:
Process begin
Constructor
Two objects is the same instance
Destructor
Is it the same as expected? Declaring a single piece as a static member in the member function can achieve both the delay instantiation and thread security purpose, and check whether the program exits at the end of the result, what about automatically calling the Destructor? In this way, we can release the resources in the destructor. When the program exits, the process will automatically release these static members.
Reference books: head first design model