c++中静态函数与动态函数的区别以及与单例模式的关系

参考:

https://zhuanlan.zhihu.com/p/37469260

https://www.cnblogs.com/zxh1210603696/p/4157294.html

https://blog.csdn.net/Wu_qz/article/details/81044823

static:

  • 静态数据成员

1、在类内数据成员前加上 static 关键字,即为静态数据成员
2、对于类静态数据成员,无论有多少个该类的对象,该静态数据成员在内存中只有一份拷贝(其他普通数据成员,每个类对象都有自己的内存拷贝),该静态数据成员由所有该类对象共享
3、静态数据成员存储在全局数据区,在定义时分配存储空间,程序运行结束时销毁
4、静态数据成员不能再类中定义和初始化,只能在类中声明,在类外进行定义和初始化,默认初始化为0
5、静态数据成员的初始化为 <类型名> <类名>::<变量名> = <值>
6、静态数据成员遵从 public private protected 访问规则
7、静态数据成员可以直接使用类名加作用域运算符(::)直接访问 <类名>::<变量名>(访问规则允许的情况下)

  • 静态成员函数

1、在普通类成员函数前加上 static 关键字,即为静态成员函数
2、在类外定义静态成员函数时,不用再加 static 关键字,只要在类中声明时加上即可
3、静态成员函数只能访问静态数据成员和静态成员函数,普通成员函数可以访问静态成员函数和静态数据成员
4、静态成员函数属于类,不属于任意一个类对象
5、静态成员函数没有 this 指针
6、可以使用 <类名>::<函数名> 访问,也可由类对象使用(./->)访问

使用静态成员函数的好处:

1、 其他文件中可以定义相同名字的函数,不会发生冲突。 
2、 静态函数不能被其他文件所用。 

单例模式的实现

单例模式是保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例并且能够被所有程序模块共享。

单例模式常常借助static函数实现,其实现步骤一般如下:

  1. 私有化它的构造函数,以防止外界创建单例类的对象;
  2. 使用类的私有静态指针变量指向类的唯一实例;
  3. 使用一个公有的静态方法获取该实例。

单线程中单例模式的实现:

class CSingleton
{
private:
    CSingleton() //构造函数是私有的
    {
    }
    static CSingleton *m_pInstance;
public:
    static CSingleton * GetInstance()
    {
        if (m_pInstance == NULL) //判断是否第一次调用
            m_pInstance = new CSingleton();
        return m_pInstance;
    }
};

这种形式单线程下是没毛病的,但是多线程下就会出现race condition,因此在多线程条件下,通常使用,DCL技法,代码如下:

Widget* Widget::pInstance{ nullptr };
Widget* Widget::Instance() {
    if (pInstance == nullptr) { // 1: first check
        lock_guard<mutex> lock{ mutW };
        if (pInstance == nullptr) { // 2: second check
            pInstance = new Widget(); 
        }
    } 
    return pInstance;
}

但是这种方法也可能会出现问题:代码中第三行代码:if (pInstance == nullptr)和第六行代码pInstance = new Widget();没有正确的同步,在某种情况下会出现new返回了地址赋值给pInstance变量而Widget此时还没有构造完全,当另一个线程随后运行到第三行时将不会进入if从而返回了不完全的实例对象给用户使用,造成了严重的错误。

改进如下:

atomic<Widget*> Widget::pInstance{ nullptr };
Widget* Widget::Instance() {
    if (pInstance == nullptr) { 
        lock_guard<mutex> lock{ mutW }; 
        if (pInstance == nullptr) { 
            pInstance = new Widget(); 
        }
    } 
    return pInstance;
}

不过也可以使用以下最为简洁的方法:

 widget& widget::get_instance() {
     static widget instance;
     return instance;
 }

猜你喜欢

转载自blog.csdn.net/kezhi9195/article/details/96148881