【发布时间】:2015-12-24 16:33:35
【问题描述】:
我一直在尝试使用 STL 的一些 C++11 特性来实现单例。我阅读了一些实现,发现这很不错:http://silviuardelean.ro/2012/06/05/few-singleton-approaches/ 我做了一些更改,得到了在 VS2013 上运行的波纹管代码,但我仍然想知道:
a) 这个实现是线程安全的吗?
b) 从 GetInstance 返回 shared_ptr 而不是引用是否可以(良好做法)?
PS.:我的单例是 OpenGL 接口(这就是名称的由来)。
HandlerOpenGL.h
#pragma once
// STL headers
#include <memory> // shared_ptr
#include <mutex> // once_flag
// OpenGL Handler Singleton
class HandlerOpenGL
{
public:
// Constructor/Destructor interface
static std::shared_ptr<HandlerOpenGL> GetInstance(void); // Only way to access singleton
~HandlerOpenGL(void);
HandlerOpenGL(const HandlerOpenGL&) = delete; // Avoid any copy/move
HandlerOpenGL(HandlerOpenGL&&) = delete;
HandlerOpenGL& operator=(const HandlerOpenGL&) = delete;
HandlerOpenGL& operator=(HandlerOpenGL&&) = delete;
private:
// Hide construction method/variables
HandlerOpenGL(void); // Private to be created once
static std::shared_ptr<HandlerOpenGL> _instance;
static std::once_flag _flag;
};
HandlerOpenGL.cpp
// Own header
#include "HandlerOpenGL.h"
// STL headers
#include <memory> // shared_ptr, make_shared
#include <mutex> // once_flag, call_once
// instanciate static members
std::shared_ptr<HandlerOpenGL> HandlerOpenGL::_instance(nullptr);
std::once_flag HandlerOpenGL::_flag;
std::shared_ptr<HandlerOpenGL> HandlerOpenGL::GetInstance(void)
{
std::call_once(_flag, [](){ _instance.reset(new HandlerOpenGL); });
return _instance;
}
HandlerOpenGL::~HandlerOpenGL(void)
{
}
HandlerOpenGL::HandlerOpenGL(void)
{
}
【问题讨论】:
-
您链接的文章有一个严重的问题:它声称 静态变量不是线程安全的。这是错误的。在 C++11 中,静态变量的初始化需要是线程安全的。因此,不需要使用
call_once进行所有这些操作。 -
非常感谢!我读过这篇文章:aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf 声称静态变量不是线程安全的,但它是从 2004 年开始的。
标签: c++ multithreading c++11 stl singleton