侧边栏壁纸
博主头像
李振洋的博客博主等级

歌颂动荡的青春

  • 累计撰写 38 篇文章
  • 累计创建 6 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录
C++

单例模式 C++

单例模式 C++

单例模式(Singleton Pattern,也称为单件模式),是保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。也就是在任何位置都可以通过接口获取到那个唯一实例。

定义一个单例类:

  • 私有化它的构造函数,以防止外界创建单例类的对象;

  • 使用类的私有静态指针变量指向类的唯一实例;

  • 使用一个公有的静态方法获取该实例。

单例模式适用于以下情况:

  1. 需要全局访问点:当一个对象需要在整个程序中被访问时,可以使用单例模式确保只有一个实例存在,并提供一个全局访问点。

  2. 资源共享:单例模式可以用来管理共享的资源,例如数据库连接、日志文件等,确保在程序的生命周期中只有一个实例存在,避免资源浪费和冲突。

  3. 控制实例个数:有些情况下,需要限制一个类只能有一个实例,这时单例模式非常有用。

  4. 延迟实例化:有时候希望对象的实例在第一次被访问时才被创建,单例模式可以实现延迟实例化,提高程序的性能。

  5. 线程池、缓存、对话框、注册表设置:在这些情景下,单例模式可以有效地管理资源或状态,确保在程序中只有一个实例存在。

局部静态变量

我们知道当一个函数中定义一个局部静态变量,那么这个局部静态变量只会初始化一次,就是在这个函数第一次调用的时候,以后无论调用几次这个函数,函数内的局部静态变量都不再初始化。 因此可以利用局部静态变量这一特点来实现单例。

//懒汉式
class Single {
private:
    Single()
    {
    }
    Single(const Single&) = delete;
    Single& operator=(const Single&) = delete;
public:
    static Single& GetInst()
    {
        static Single single;
        return single;
    }
};

void test_single()
{
    //C11之前多线程情况下可能存在问题 
    cout << "s1 addr is " << &Single::GetInst() << endl;
    cout << "s2 addr is " << &Single::GetInst() << endl;
}

程序输出如下

sp1  is  0x1304b10
sp2  is  0x1304b10

静态成员变量指针方式

//饿汉式
class Single2Hungry
{
private:
    Single2Hungry()
    {
    }
    Single2Hungry(const Single2Hungry &) = delete;
    Single2Hungry &operator=(const Single2Hungry &) = delete;

public:
    static Single2Hungry *GetInst()
    {
        if (single == nullptr)
        {
            single = new Single2Hungry();
        }
        return single;
    }

private:
    static Single2Hungry *single;
};

饿汉式的方式可以避免线程安全问题

//饿汉式初始化
Single2Hungry *Single2Hungry::single = Single2Hungry::GetInst();
void thread_func_s2(int i)
{
    cout << "this is thread " << i << endl;
    cout << "inst is " << Single2Hungry::GetInst() << endl;
}
void test_single2hungry()
{
    cout << "s1 addr is " << Single2Hungry::GetInst() << endl;
    cout << "s2 addr is " << Single2Hungry::GetInst() << endl;

    for (int i = 0; i < 3; i++)
    {
        thread tid(thread_func_s2, i);
        tid.join();
    }
}
int main(){
    test_single2hungry()
}

程序输出

s1 addr is 0x1e4b00
s2 addr is 0x1e4b00
this is thread 0
inst is 0x1e4b00
this is thread 1
inst is 0x1e4b00
this is thread 2
inst is 0x1e4b00

单线程还是多线程模式下,通过静态成员变量的指针实现的单例类都是唯一的。

无论饿汉式还是懒汉式都存在一个问题,就是什么时候释放内存?多线程情况下,释放内存就很难了,还有二次释放内存的风险。

智能指针方式

利用智能指针自动回收内存的机制设计单例类

//safe deletor
//防止外界delete
//声明辅助类
//该类定义仿函数调用SingleAutoSafe析构函数
//不可以提前声明SafeDeletor,编译时会提示incomplete type
// class SafeDeletor;
//所以要提前定义辅助类
class SingleAutoSafe;
class SafeDeletor
{
public:
    void operator()(SingleAutoSafe *sf)
    {
        cout << "this is safe deleter operator()" << endl;
        delete sf;
    }
};
class SingleAutoSafe
{
private:
    SingleAutoSafe() {}
    ~SingleAutoSafe()
    {
        cout << "this is single auto safe deletor" << endl;
    }
    SingleAutoSafe(const SingleAutoSafe &) = delete;
    SingleAutoSafe &operator=(const SingleAutoSafe &) = delete;
    //定义友元类,通过友元类调用该类析构函数
    friend class SafeDeletor;

public:
    static std::shared_ptr<SingleAutoSafe> GetInst()
    {
        if (single != nullptr)
        {
            return single;
        }

        s_mutex.lock();
        if (single != nullptr)
        {
            s_mutex.unlock();
            return single;
        }
        //额外指定删除器
        single = std::shared_ptr<SingleAutoSafe>(new SingleAutoSafe, SafeDeletor());
        //也可以指定删除函数
        // single = std::shared_ptr<SingleAutoSafe>(new SingleAutoSafe, SafeDelFunc);
        s_mutex.unlock();
        return single;
    }

private:
    static std::shared_ptr<SingleAutoSafe> single;
    static mutex s_mutex;
};

通用的单例模板类

template <typename T>
class Single_T
{
protected:
    Single_T() = default;
    Single_T(const Single_T<T> &st) = delete;
    Single_T &operator=(const Single_T<T> &st) = delete;
    ~Single_T()
    {
        cout << "this is auto safe template destruct" << endl;
    }

public:
    static std::shared_ptr<T> GetInst()
    {
        if (single != nullptr)
        {
            return single;
        }

        s_mutex.lock();
        if (single != nullptr)
        {
            s_mutex.unlock();
            return single;
        }
        //额外指定删除器
        single = std::shared_ptr<T>(new T, SafeDeletor_T<T>());
        //也可以指定删除函数
        // single = std::shared_ptr<SingleAutoSafe>(new SingleAutoSafe, SafeDelFunc);
        s_mutex.unlock();
        return single;
    }

private:
    static std::shared_ptr<T> single;
    static mutex s_mutex;
};

//模板类的static成员要放在h文件里初始化
template <typename T>
std::shared_ptr<T> Single_T<T>::single = nullptr;

template <typename T>
mutex Single_T<T>::s_mutex;

0

评论区