IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 5、创建型模式——单例模式(Singleton) -> 正文阅读

[C++知识库]5、创建型模式——单例模式(Singleton)

1、动机

对于系统中的某些类来说,只有一个实例化对象很重要。

  • 普通类的对象,既可以叫对象,也可以叫实例化对象(实例)
  • 抽象类是不可以被实例化的,那它的对象就不能叫实例化对象,只能叫对象

如何保证一个类只有一个实例化对象且这个实例化对象易于被访问呢?

  • 定义一个全局变量可以确保实例化对象随时都可以被访问,但不能防止我们实例化多个对象。
  • 好的解决办法:让类自身负责保存它的唯一实例化对象。这个类可以保证没有其他实例化对象被创建,并且它可以提供一个访问该实例化对象的方法。

2、实现方式

a)在类中添加一个私有静态成员变量用于保存单例实例化对象

b)声明一个公有静态构建方法用于获取单例实例化对象

c)在静态方法中实现"延迟初始化"。该方法会在首次被调用时创建一个实例化对象,并将其存储在静态成员变量中。此后该方法每次被调用时都返回该实例。

d)将类的构造函数设为私有。类的静态方法仍能调用构造函数,但是其他对象不能调用。

e)检查客户端代码,将对单例的构造函数的调用替换为对其静态构建方法的调用。

3、类图

4、代码

4.1饿汉模式

// Singleton.h
#ifndef SINGLETON_H_
#define SINGLETON_H_

class Singleton
{
public:
    static Singleton* GetInstance()
    {
       return instance_;
    }
private:
    Singleton(){}

private:
    static Singleton* instance_;
};

#endif //SINGLETON_H_


// Singleton.cpp
#include "Singleton.h"
Singleton* Singleton::instance_ = new Singleton();

//main.cpp
#include <iostream>
#include "Singleton.h"

int main() {
    Singleton *s1 = Singleton::GetInstance();
    Singleton *s2 = Singleton::GetInstance();

    std::cout << "s1地址: " << s1 << std::endl;
    std::cout << "s2地址: " << s2 << std::endl;
    return 0;
}

4.2懒汉模式

4.2.1 线程不安全懒汉模式
// Singleton.h
#ifndef SINGLETON_H_
#define SINGLETON_H_

class Singleton
{
public:
    static Singleton* GetInstance()
    {
       if(instance_ == nullptr)
       {
           instance_ = new Singleton();
       } 
       return instance_;
    }
private:
    Singleton(){}

private:
    static Singleton* instance_;
};

#endif //SINGLETON_H_

// Singleton.cpp
#include "Singleton.h"

//静态变量instance_的初始化不能放在头文件,不然多个文件#include "Singleton.h"会出现重复定义问题
Singleton* Singleton::instance_ = nullptr;

//main.cpp
#include<iostream>
#include"Singleton.h"

int main()
{
    Singleton* s1 = Singleton::GetInstance();
    Singleton* s2 = Singleton::GetInstance();

    std::cout<<"s1的地址为:"<<s1<<std::endl;
    std::cout<<"s2的地址为:"<<s2<<std::endl;
    return 0;
}
4.2.2 线程安全懒汉模式
// Singleton.h
#ifndef SINGLETON_H_
#define SINGLETON_H_
#include<mutex>

class Singleton
{
public:
    static Singleton* GetInstance()
    {
       if(instance_ == nullptr)
       {
           //加锁保证多个线程并发调用getInstance()时只会创建一个实例
           m_mutex_.lock();
           if(instance_ == nullptr)
           {
               instance_ = new Singleton();
           }
           m_mutex_.unlock();
       } 
       return instance_;
    }
private:
    Singleton(){}

private:
    static Singleton* instance_;
    static std::mutex m_mutex_;
};

#endif //SINGLETON_H_


// Singleton.cpp
#include "Singleton.h"

//静态变量instance_的初始化不能放在头文件,不然多个文件#include "Singleton.h"会出现重复定义问题
Singleton* Singleton::instance_ = nullptr;
std::mutex Singleton::m_mutex_;


//main.cpp
#include<iostream>
#include "Singleton.h"

int main()
{
    Singleton* s1 = Singleton::GetInstance();
    Singleton* s2 = Singleton::GetInstance();

    std::cout<<"s1的地址为:"<<s1<<std::endl;
    std::cout<<"s2的地址为:"<<s2<<std::endl;
    return 0;
}

4.3 Meyers’ Singleton

Meyers’ Singleton是Scott Meyers提出的C++单例的推荐写法。它将单例对象作为局部static对象定义在函数内部:

#ifndef SINGLETON_H_
#define SINGLETON_H_

class Singleton {
 public:
    static Singleton& GetInstance() {
        static Singleton instance;
        return instance;
    }
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

 private:
    Singleton() {}
};

#endif  // SINGLETON_H_

优点:

  • 解决了普通单例模式全局变量初始化依赖(C++只能保证在同一个文件中声明的static遍历初始化顺序和其遍历声明的顺序一致,但是不能保证不同文件中static遍历的初始化顺序)

缺点:

  • 需要C++11支持(C++11保证static成员初始化的线程安全)
  • 性能问题(同懒汉模式一样,每次调用GetInstance()方法时需要判断局部static变量是否已经初始化,如果没有初始化就会进行初始化,这个判断逻辑会消耗一点性能)
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-31 23:45:54  更:2022-03-31 23:49:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 1:47:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码