当前位置: 首页 > news >正文

c++懒汉式单例模式(Singleton)多种实现方式及最优比较

前言

关于C++懒汉式单例模式的写法,大家都很熟悉。早期的设计模式中有代码示例。比如:

class Singleton {private: static Singleton *instance;public: static Singleton *getInstance() {if (NULL == instance)instance = new Singleton();return instance;}
};

它的缺点:线程不安全,指针资源没有释放。

自从C++11推出后,单例模式有了更优秀的写法,下面来介绍下。

使用 std::call_once 实现

#include <iostream>
#include <mutex>
#include <memory>class Singleton {
private:Singleton() { std::cout << "Singleton constructed." << std::endl; }static std::once_flag initInstanceFlag;static std::unique_ptr<Singleton> instance;// 删除拷贝构造函数和赋值操作符Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;public:static Singleton& getInstance() {std::call_once(initInstanceFlag, []() {instance.reset(new Singleton());});return *instance;}void someMethod() {std::cout << "Method of the singleton" << std::endl;}~Singleton() {std::cout << "Singleton destructed." << std::endl;}
};std::once_flag Singleton::initInstanceFlag;
std::unique_ptr<Singleton> Singleton::instance;// 使用示例
void threadFunction() {Singleton& singleton = Singleton::getInstance();singleton.someMethod();
}int main() {std::thread t1(threadFunction);std::thread t2(threadFunction);t1.join();t2.join();return 0;
}

优点:线程安全、内存安全。显式控制初始化过程,适合需要延迟初始化的场景。

使用局部静态变量实现(C++11及以后)

#include <iostream>
#include <memory>class Singleton {
private:Singleton() { std::cout << "Singleton constructed." << std::endl; }// 关闭拷贝构造函数、右值拷贝构造函数和赋值操作符Singleton(const Singleton&) = delete;Singleton(const Singleton &&) = delete;Singleton& operator=(const Singleton&) = delete;public:static Singleton& getInstance() {static Singleton instance;return instance;}void someMethod() {std::cout << "Method of the singleton" << std::endl;}~Singleton() {std::cout << "Singleton destructed." << std::endl;}
};// 使用示例
void threadFunction() {Singleton& singleton = Singleton::getInstance();singleton.someMethod();
}int main() {std::thread t1(threadFunction);std::thread t2(threadFunction);t1.join();t2.join();return 0;
}

优点:线程安全。代码最简洁,由C++11标准保证线程安全,适合大多数场景。
缺点:适用于不复杂的工程。因为如果静态类之间有依赖,可能会导致C++的一些未定义的行为。

Meyers 的版本

Scott Meyers 是 Effective C++系列的作者,他最早提供了简洁版本的 Singletion 模型。根据他提供的模型,可以写出线程安全又简单的单例模式。代码如下:

#include <stdio.h>class singleton {static singleton &instance() {static singleton instance;return instance;} // instancesingleton(const singleton &) = delete;singleton & operator = (const singleton &) = delete;private:singleton() {}~singleton() {}public:void out(){ printf("out\n"); }
}; // struct singletonint main() {singleton::instance().out();return 0;
}

缺点:单一的实例总是在 main() 开始之前被初始化的,该实现无法做到 lazyinit。
优化版本:

 template<typename T>class singleton {public:static T &instance();singleton(const singleton &) = delete;singleton &operator=(const singleton) = delete;protected:singleton() = default;};template<typename T>inline T &singleton<T>::instance() {static const std::unique_ptr<T> instance{new T{token{}}};return *instance;}

优点:线程安全、内存安全。

鸿蒙单例实现

线程安全、内存安全、双重检测、延迟加载、支持lazyinit、实现懒汉式单例模板。当前在商业(鸿蒙手机操作系统)使用中,代码可靠。
使用说明,请点这里。
下面只展示DelayedSingleton实现示例。完整代码以及其它几种单例实现,请点这里。
补充说明:对于懒汉式单例模式双重检测,有的人嫌代码麻烦,将构造函数私有化来实现。这个大家自己去评价。其实也没几行代码。写上双重检测,逻辑上也是提醒大家代码实现的风险点。不算优化问题。论可靠,还是相信鸿蒙吧。

template<typename T>
class DelayedSingleton : public NoCopyable {
public:static std::shared_ptr<T> GetInstance();static void DestroyInstance();private:static std::shared_ptr<T> instance_;  instance.static std::mutex mutex_; 
};template<typename T>
std::shared_ptr<T> DelayedSingleton<T>::instance_ = nullptr;template<typename T>
std::mutex DelayedSingleton<T>::mutex_;template<typename T>
std::shared_ptr<T> DelayedSingleton<T>::GetInstance()
{if (instance_ == nullptr) {std::lock_guard<std::mutex> lock(mutex_);if (instance_ == nullptr) {std::shared_ptr<T> temp(new (std::nothrow) T);instance_ = temp;}}return instance_;
}template<typename T>
void DelayedSingleton<T>::DestroyInstance()
{std::lock_guard<std::mutex> lock(mutex_);if (instance_ != nullptr) {instance_.reset();instance_ = nullptr;}
}
http://www.lryc.cn/news/431584.html

相关文章:

  • Gartner《2024中国安全技术成熟度曲线》AI安全助手代表性产品:开发者安全助手D10
  • 奇安信椒图--服务器安全管理系统(云锁)
  • pointer-events,添加水印的一个小小点
  • 微服务--认识微服务
  • 【docker】docker 镜像仓库的管理
  • 第L2周:机器学习-线性回归
  • SpringMVC拦截器深度解析与实战
  • 直线上最多的点数
  • 经济管理专业数据库介绍
  • 【C++ Primer Plus习题】11.1
  • [数据库][oracle]ORACLE EXP/IMP的使用详解
  • 中国各银行流动性比例数据(2000-2022年)
  • MACOS安装配置前端开发环境
  • Docker 配置国内镜像源
  • AI模块在人工智能中扮演着什么样的角色
  • VM Workstation虚拟机AlmaLinux 9.4操作系统安装(桌面版安装详细教程)(宝塔面板的安装),填补CentOS终止支持维护的空白
  • 【学习笔记】卫星通信NTN 3GPP标准化进展分析(三)- 3GPP Release17 内容
  • 【SQL】常见语句合集
  • Cozer必备!一站式解锁扣子全网最全插件集锦(三)
  • 1-2宿主环境
  • Java进阶13讲__第九讲
  • 上海市计算机学会竞赛平台2024年8月月赛丙组等差数列的素性
  • VR虚拟展厅的应用场景有哪些?
  • Go 语言版本管理——Goenv
  • C#中的各种画刷, PathGradientBrush、线性渐变(LinearGradientBrush)和径向渐变的区别
  • 如何在Mac中修改pip的镜像源
  • MySQL你必须知道的事
  • Ceph RBD使用
  • Spark MLlib模型训练—回归算法 Random forest regression
  • 华为OD机试真题-数大雁-2024年OD统一考试(E卷)