任何人都可以为我提供 C++ 中的单例示例吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/270947/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can any one provide me a sample of Singleton in c++?
提问by user25749
I write a singleton c++ in the follow way:
我用以下方式编写了一个单例 C++:
class A {
private:
static A* m_pA;
A();
virtual ~A();
public:
static A* GetInstance();
static void FreeInstance();
void WORK1();
void WORK2();
void WORK3();
}
}
A* A::GetInstance() {
if (m_pA == NULL)
m_pA = new A();
return m_pA;
}
A::~A() {
FreeInstance() // Can I write this? are there any potential error?
}
void A::FreeInstance() {
delete m_pA;
m_pA = NULL;
}
Thanks! Evan Teran and sep61.myopenid.com 's answer is right, and really good! My way is wrong, I wish any one writting such code can avoid my silly mistake.
谢谢!Evan Teran 和 sep61.myopenid.com 的回答是正确的,而且非常好!我的方法是错误的,我希望任何编写此类代码的人都可以避免我的愚蠢错误。
My singleton A in my project has a vector of smart pointer, and another thread can also edit this vector, so when the application is closing, it always become unstable even I add lots of CMutex. Multithread error + singleton error wasted me 1 day.
我的项目中的单例A有一个智能指针向量,另一个线程也可以编辑这个向量,所以当应用程序关闭时,即使我添加了很多CMutex,它也会变得不稳定。多线程错误 + 单例错误浪费了我 1 天。
//----------------------------------------------------------- A new singleton, you are welcome to edit if you think there is any problem in the following sample:
//------------------------------------------------ ----------- 一个新的单例,如果您认为以下示例有问题,欢迎您编辑:
class A {
private:
static A* m_pA;
explicit A();
void A(const A& a);
void A(A &a);
const A& operator=(const A& a);
virtual ~A();
public:
static A* GetInstance();
static void FreeInstance();
void WORK1();
void WORK2();
void WORK3();
}
}
A* A::GetInstance() {
if (m_pA == NULL){
static A self;
m_pA = &self;
}
return m_pA;
}
A::~A() {
}
采纳答案by Evan Teran
You can avoid needing to delete it by using a static object like this:
您可以通过使用像这样的静态对象来避免删除它:
if(m_pA == 0) {
static A static_instance;
m_pA = &static_instance;
}
回答by Martin York
Why does everybody want to return a singleton as a pointer?
Return it as a reference seems much more logical!
为什么每个人都想返回一个单例作为指针?
将其作为参考返回似乎更合乎逻辑!
You should never be able to free a singleton manually. How do you know who is keeping a reference to the singleton? If you don't know (or can't guarantee) nobody has a reference (in your case via a pointer) then you have no business freeing the object.
您永远无法手动释放单身人士。你怎么知道谁在保持对单身人士的引用?如果您不知道(或不能保证)没有人有引用(在您的情况下是通过指针),那么您就没有办法释放该对象。
Use the static in a function method.
This guarantees that it is created and destroyed only once. It also gives you lazy initialization for free.
在函数方法中使用静态。
这保证它只被创建和销毁一次。它还免费为您提供延迟初始化。
class S
{
public:
static S& getInstance()
{
static S instance;
return instance;
}
private:
S() {}
S(S const&); // Don't Implement.
void operator=(S const&); // Don't implement
};
Note you also need to make the constructor private. Also make sure that you override the default copy constructor and assignment operator so that you can not make a copy of the singleton (otherwise it would not be a singleton).
请注意,您还需要将构造函数设为私有。还要确保你覆盖了默认的复制构造函数和赋值运算符,这样你就不能复制单例(否则它不会是单例)。
Also read:
另请阅读:
- https://stackoverflow.com/a/1008289/14065
- Singleton: How should it be used
- C++ Singleton design pattern
To make sure you are using a singleton for the correct reasons.
确保您出于正确的原因使用单例。
Though technically not thread safe in the general case see:
What is the lifetime of a static variable in a C++ function?
尽管在一般情况下技术上不是线程安全的,请参阅:
什么是 C++ 函数中静态变量的生命周期?
GCC has an explicit patch to compensate for this:
http://gcc.gnu.org/ml/gcc-patches/2004-09/msg00265.html
GCC 有一个明确的补丁来弥补这一点:http:
//gcc.gnu.org/ml/gcc-patches/2004-09/msg00265.html
回答by sep
A singleton in C++ can be written in this way:
C++ 中的单例可以这样写:
static A* A::GetInstance() {
static A sin;
return &sin;
}
回答by Jasper Bekkers
Just don't forget to make the copy constructor and assignment operators private.
只是不要忘记将复制构造函数和赋值运算符设为私有。
回答by Odd
I do not think there is any reason to write that line no. Your destructor method is not static and your singleton instance will not be destructed in that fashion. I do not think the destructor is necessary, if you need to cleanup the object use the static method you've alread created, FreeInstance().
我不认为有任何理由写那行没有。您的析构函数方法不是静态的,并且您的单例实例不会以这种方式被破坏。我不认为析构函数是必要的,如果您需要使用您已经创建的静态方法 FreeInstance() 清理对象。
Other than that, you create your singletons in roughly the same way that I create mine.
除此之外,您创建单身人士的方式与我创建单身人士的方式大致相同。
回答by Will Dean
After a period of wild enthusiasm for Meyers-style singletons (using local static objects as in some of the previous answers), I got completely sick of the lifetime management problems in complicated apps.
在对 Meyers 风格的单例(使用本地静态对象,就像之前的一些答案中一样)狂热了一段时间之后,我完全厌倦了复杂应用程序中的生命周期管理问题。
I tend to find that you end up referencing the 'Instance' method deliberately early in the app's initialisation, to make sure they're created when you want, and then playing all kinds of games with the tear-down because of the unpredictable (or at least very complicated and somewhat hidden) order in which things get destroyed.
我倾向于发现您最终会在应用程序初始化的早期故意引用“实例”方法,以确保它们是在您想要的时候创建的,然后由于不可预测的(或至少非常复杂且有些隐蔽)事物被破坏的顺序。
YMMV of course, and it depends a bit on the nature of the singleton itself, but a lot of the waffle about clever singletons (and the threading/locking issues which surround the cleverness) is overrated IMO.
当然是 YMMV,这在一定程度上取决于单身人士本身的性质,但是很多关于聪明单身人士的华夫饼(以及围绕聪明人的线程/锁定问题)被高估了 IMO。
回答by jab
if you read "Modern C++ Design" you'll realize that a singleton design could be much complex than return a static variable.
如果您阅读“现代 C++ 设计”,您会意识到单例设计可能比返回静态变量复杂得多。
回答by n-alexander
This implementation is fine as long as you can answer these questions:
只要你能回答以下问题,这个实现就很好:
do you know when the object will be created (if you use a static object instead of new? Do you have a main()?)
does you singleton have any dependencies that may not be ready by the time it is created? If you use a static object instead of new, what libraries have been initialized by this time? What your object does in constructor that might require them?
when will it be deleted?
你知道什么时候创建对象吗(如果你使用静态对象而不是新对象?你有 main() 吗?)
您是否有任何在创建时可能尚未准备就绪的依赖项?如果使用静态对象而不是新对象,此时已经初始化了哪些库?您的对象在可能需要它们的构造函数中做了什么?
什么时候会被删除?
Using new() is safer because you control where and when the object will be created and deleted. But then you need to delete it explicitly and probably nobody in the system knows when to do so. You may use atexit() for that, if it makes sense.
使用 new() 更安全,因为您可以控制创建和删除对象的位置和时间。但是随后您需要明确删除它,而且系统中可能没有人知道何时这样做。如果有意义,您可以使用 atexit() 。
Using a static object in method means that do do not really know when it will be created or deleted. You could as well use a global static object in a namespace and avoid getInstance() at all - it doesn't add much.
在方法中使用静态对象意味着并不真正知道它何时会被创建或删除。您也可以在命名空间中使用全局静态对象并完全避免 getInstance() - 它不会增加太多。
If you do use threads, then you're in big trouble. It is virtually impossible to create usable thread safe singleton in C++ due to:
如果您确实使用线程,那么您将遇到大麻烦。由于以下原因,几乎不可能在 C++ 中创建可用的线程安全单例:
- permanent lock in getInstance is very heavy - a full context switch at every getInstance()
- double checked lock fails due to compiler optimizations and cache/weak memory model, is very tricky to implement, and impossible to test. I wouldn't attempt to do it in a real system, unless you intimately know your architecture and want it to be not portable
- getInstance 中的永久锁定非常重 - 每个 getInstance() 的完整上下文切换
- 由于编译器优化和缓存/弱内存模型,双重检查锁失败,实现起来非常棘手,并且无法测试。我不会尝试在真实系统中执行此操作,除非您非常了解自己的架构并希望它不可移植
These can be Googled easily, but here's a good link on weak memory model: http://ridiculousfish.com/blog/archives/2007/02/17/barrier.
这些可以很容易地在谷歌上搜索,但这里有一个关于弱内存模型的好链接:http: //ridiculousfish.com/blog/archives/2007/02/17/barrier。
One solution would be to use locking but require that users cache the pointer they get from getInctance() and be prepared for getInstance() to be heavy.
一种解决方案是使用锁定,但要求用户缓存他们从 getInctance() 获得的指针,并准备好让 getInstance() 变重。
Another solution would be to let users handle thread safety themselves.
另一种解决方案是让用户自己处理线程安全。
Yet another solution would be to use a function with simple locking and substitute it with another function without locking and checking once the new() has been called. This works, but full implementation is complicated.
另一种解决方案是使用具有简单锁定的函数,并在调用 new() 后不锁定和检查的情况下将其替换为另一个函数。这有效,但完整的实现很复杂。
回答by amightywind
//! @file singleton.h
//!
//! @brief Variadic template to make a singleton out of an ordinary type.
//!
//! This template makes a singleton out of a type without a default
//! constructor.
#ifndef SINGLETON_H
#define SINGLETON_H
#include <stdexcept>
template <typename C, typename ...Args>
class singleton
{
private:
singleton() = default;
static C* m_instance;
public:
singleton(const singleton&) = delete;
singleton& operator=(const singleton&) = delete;
singleton(singleton&&) = delete;
singleton& operator=(singleton&&) = delete;
~singleton()
{
delete m_instance;
m_instance = nullptr;
}
static C& create(Args...args)
{
if (m_instance != nullptr)
{
delete m_instance;
m_instance = nullptr;
}
m_instance = new C(args...);
return *m_instance;
}
static C& instance()
{
if (m_instance == nullptr)
throw std::logic_error(
"singleton<>::create(...) must precede singleton<>::instance()");
return *m_instance;
}
};
template <typename C, typename ...Args>
C* singleton<C, Args...>::m_instance = nullptr;
#endif // SINGLETON_H
回答by amightywind
There is a great C++ library, ACE, based on patterns. There's a lot of documentation about different kind of patterns so look at their work: http://www.cs.wustl.edu/~schmidt/ACE.html
有一个很棒的 C++ 库,ACE,基于模式。有很多关于不同类型模式的文档,所以看看他们的工作:http: //www.cs.wustl.edu/~schmidt/ACE.html