c++11单例模式写法推荐
·
文章目录
饿汉模式的对象在类产生时候就创建了,一直到程序结束才会去释放。即作为一个单例类实例,它的生存周期和我们的程序一样长。因此该实例对象需要存储在全局数据区,所以肯定需要使用static来修饰,因为类内部的static成员是不属于每个对象的,而是属于整个类的。
如果有多个动态链接库,链接库中都引用了单例类,每个单例类在动态链库中都是唯一的,这个就和单例的期望不一样(单例不唯一了),如果要唯一的话,加上 -rdynamic 编译参数
手动释放
#ifndef SINGLETON_H
#define SINGLETON_H
/* 饿汉式
* 线程安全,稍浪费内存,空间换时间。我推荐用这种
* 懒汉式不推荐
* 在懒汉模式中,如果用到双检查锁,请注意双检查锁中内存reorder引发的问题
*
* */
#include <iostream>
class Singleton
{
private:
Singleton(){std::cout << "construct it" << std::endl;}
Singleton(const Singleton&) = delete;
Singleton(Singleton&&) noexcept = delete;
Singleton& operator=(const Singleton&) = delete;
Singleton& operator=(Singleton&&) noexcept = delete;
//析构函数我们也需要声明成private的
//因为我们想要这个实例在程序运行的整个过程中都存在
//所以我们不允许实例自己主动调用析构函数释放对象
~Singleton() { std::cout << "in deconstructor" << std::endl;};
private:
static Singleton* m_pSingleton;
public:
static Singleton* getInstance();
static void freeInstance();
};
#endif // SINGLETON_H
#include "singleton.h"
// 静态变量是一个指针
// 程序运行完成后,不会自动删除指向的堆内存(这好像是常识),哈哈
// 所以在最后必须调用 delete
Singleton* Singleton::m_pSingleton = new Singleton();
Singleton* Singleton::getInstance()
{
return m_pSingleton;
}
void Singleton::freeInstance()
{
std::cout << "free it" << std::endl;
if (NULL != m_pSingleton)
{
delete m_pSingleton; // 在静态函数中delete一个对象,当然也会调用这个对象的析构函数
m_pSingleton = NULL;
}
}
#include <iostream>
#include "singleton.h"
int main(int argc, char** argv)
{
Singleton* p1 = Singleton::getInstance();
Singleton* p2 = Singleton::getInstance();
if (p1 == p2)
{
std::cout << "success" << std::endl;
}else
{
std::cout << "failed" << std::endl;
}
Singleton::freeInstance();
return 0;
}
/*
construct it
success
free it
in deconstructor
*/
智能指针
#include <iostream>
#include <memory>
using std::cout;
using std::endl;
class Singleton{
private:
Singleton(){
cout << "创建了一个单例对象" << endl;
}
Singleton(const Singleton&) = delete;
Singleton(Singleton&&) noexcept = delete;
Singleton& operator=(const Singleton&) = delete;
Singleton& operator=(Singleton&&) noexcept = delete;
~Singleton(){
// 析构函数我们也需要声明成private的
// 不允许实例自己主动调用析构函数释放对象,比如 delete p_obj
cout << "销毁了一个单例对象" << endl;
}
private:
static std::shared_ptr<Singleton> instance; //这是我们的单例对象,它是一个类对象的指针
public:
static std::shared_ptr<Singleton> getInstance();
};
// 下面这个静态成员变量在类加载的时候就已经初始化好了
std::shared_ptr<Singleton> Singleton::instance(new Singleton(), [](Singleton* t){delete t;}); // lambda表达式就可以
// std::shared_ptr<Singleton> Singleton::instance(new Singleton()) // 因为默认访问不了private 析构函数
std::shared_ptr<Singleton> Singleton::getInstance(){
return instance;
}
int main()
{
cout << "Now we get the instance" << endl;
std::shared_ptr<Singleton> instance1 = Singleton::getInstance();
std::shared_ptr<Singleton> instance2 = Singleton::getInstance();
std::shared_ptr<Singleton> instance3 = Singleton::getInstance();
cout << "Now we destroy the instance" << endl;
return 0;
}
/*
创建了一个单例对象
Now we get the instance
Now we destroy the instance
销毁了一个单例对象
*/
/*
https://stackoverflow.com/questions/14801591/calling-private-destructor-as-deleter-for-stdshared-ptr-using-lambda
The standard says in 5.1.2/3
The type of the lambda-expression [...] is a unique [...] class type — called the closure type [...] The closure type is declared in the smallest block scope, class scope, or namespace scope that contains the corresponding lambda-expression.
This means that a lambda that occurs inside a (member) function is treated like a local class, declared at block scope in the surrounding function. About local classes, the standard says in 9.8/1:
[...] The local class is in the scope of the enclosing scope, and has the same access to names outside the function as does the enclosing function.[...]
Thus the lambda has the same access as the containing member function, which means that it can access private members of the class.
If a lambda occurs directly in a class scope, it would be treated as a nested class, for which a similar rule applies: 11.7/1 says:
A nested class is a member and as such has the same access rights as any other member.
Either way, a lambda that occurs within in the scope of a class has access to private class members. So your example is fine.
(The post you referred to, ultimately was about a problem accessing protected members of base classes named by a qualified-id.)
*/
C++11 懒汉模式
class S
{
public:
static S& getInstance()
{
static S instance; // Guaranteed to be destroyed.
// Instantiated on first use.
return instance;
}
private:
S() {} // Constructor? (the {} brackets) are needed here.
// C++ 03
// ========
// Don't forget to declare these two. You want to make sure they
// are inaccessible(especially from outside), otherwise, you may accidentally get copies of
// your singleton appearing.
S(S const&); // Don't Implement
void operator=(S const&); // Don't implement
// C++ 11
// =======
// We can use the better technique of deleting the methods
// we don't want.
public:
S(S const&) = delete;
void operator=(S const&) = delete;
// Note: Scott Meyers mentions in his Effective Modern
// C++ book, that deleted functions should generally
// be public as it results in better error messages
// due to the compilers behavior to check accessibility
// before deleted status
};
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)