Dea*_*pog 3 c++ g++ visual-c++ c++03
我试图创建一个单身时想出了这个.示例:(我正在尝试创建MySelf
一个单例,它是线程安全的,不使用双重检查锁定)
class MySelf
{
private:
string Name;
int Age;
MySelf()
{
Name = "Deamonpog";
Age = 24;
cout << "Constructing MySelf : " << Name << endl;
};
friend class MySingleton;
public:
~MySelf(){ cout << "Destructing MySelf : " << Name << endl; };
int MyAge() const
{
return Age;
}
};
class MySingleton
{
private:
static MySelf mself;
public:
static MySelf * GetInstance()
{
return &mself;
}
};
MySelf MySingleton::mself;
Run Code Online (Sandbox Code Playgroud)
现在我可以很容易地使用它,像
cout << "I am " << MySingleton::GetInstance()->MyAge() << endl;
Run Code Online (Sandbox Code Playgroud)
我不想要延迟初始化,因为我要创建的类将从头到尾.但这个线程安全吗?(据我所知,似乎没问题)
如果这没关系,那么我应该使用这样的通用编程,
template <class T>
class GenericSingleton
{
private:
static T _instance;
public:
static T * GetInstance()
{
return &_instance;
}
};
template <class T>
T GenericSingleton<T>::_instance;
Run Code Online (Sandbox Code Playgroud)
所以我也可以和其他任何课程一起使用.我只需要添加friend class GenericSingleton<MySelf>;
到所需的sigleton(例如到MySelf类).
这种实施能否带来麻烦?我实际上正在创建一个库.有些单身人士要出口,有些则不出口.如果这不是一个库而只是另一个应用程序呢?
- 编辑 -
所以现在我必须这样做(因为我使用的VC++仍然不支持C++ 11),
static MySelf & GetInstance()
{
WaitForMutex(mymutex); // some function from the threading library
if( NULL == _instance )
{
_instance = new MySelf();
}
ReleaseMutex(mymutex); // release function of the same library
Return _instance;
}
Run Code Online (Sandbox Code Playgroud)
并告诉用户使用该功能一次,然后将其缓存以供使用.(或者我也可以将函数重命名为Initialize()
并生成另一种方法,只需返回引用而无需任何锁定或创建.)那么它mymutex
应该在哪里?它应该在哪里初始化?
不,但这不是主要问题.
全局对象(例如static
)的初始化在翻译单元之间是无序的; 这意味着如果在创建一个全局的过程中我正在调用,MySingleton::GetInstance()
我最终会得到一个指向单元化内存的指针.
请参阅初始化订单Fiasco.
最重要的是,如果我在初始化阶段期间启动了第二个线程,它可以访问部分初始化的对象.
一般来说,建议使用Meyer的Singleton:
MySelf& MySelf::Instance() { static MySelf S; return S; }
Run Code Online (Sandbox Code Playgroud)
它以两种方式回避初始化顺序fiasco:
Instance()
返回时初始化对象此外,从C++ 11开始,这需要是线程安全的:也就是说,Instance()
在构造对象时应该另一个线程调用它将耐心等待直到构造结束,然后返回与所有其他实例相同的实例线程(gcc已在C++ 03中完成).
注意:使用无关的类只是更多的输入没有附加值,抛弃它.
这是更简单的实现:
template <class T>
class GenericSingleton
{
public:
static T& GetInstance()
{
static T _instance;
return _instance;
}
};
Run Code Online (Sandbox Code Playgroud)
它在C++ 11中也是线程安全的,因为静态变量在任何线程之前创建.