C++从入门到放弃之:静态成员与单例模式的实现

静态成员

静态成员变量

  • 语法
class 类名{
public:
private:
	static 数据类型 变量名;//静态成员变量声明
};
数据类型 类名::变量名 = 初值;//定义和初始化
  • 对于普通的成员变量变量属于对象,对于静态成员变量变量不属于对象,类中的静态成员变量可以直接通过类名 + 静态成员变量名直接访问,相当于共享资源
  • 普通成员变量在构造对象时定义和初始化,而静态成员变量需要在类的外部单独定义和初始化,const修饰的带有常属性的静态成员变量需要在声明的同时进行初始化
  • 静态成员变量全局变量类似,被存放在全局区(数据区/BSS区),可以把静态成员变量理解为被限制在类中使用的全局成员变量
  • 静态成员变量的使形式
  1. 类名::静态成员变量;
  2. 对象.静态成员变量;

静态成员函数

  • 静态成员函数语法
class 类名 {
	//静态成员函数的声明
	static 返回值类型 函数名(形参表){
		/*函数体*/
	}
};
  • 静态成员函数没有this指针,也没有const属性,可以把静态成员函数理解为被限制在类中使用的全局函数
  • 静态成员函数只能访问类中的静态成员,而非静态成员函数既可以访问静态成员也可以访问非静态成员
  • 静态成员函数的使用形式
  1. 类名::静态成员函数(形参表);//如果没有参数,要保留()
  2. 对象.静态成员函数(实参表);

单例模式

  • 概念
    要求一个类值允许实例化唯一的一个对象,并且提供其访问方法
  • 实现思路
  1. 禁止在类的外部创建对象:私有构造函数以及拷贝构造函数,禁止生成默认的拷贝构造
  2. 类的内部维护唯一的对象:静态成员变量
#include <iostream>
class A {
private:
	static A m_a;//使用静态成员来确保唯一对象
};
int main(){
	return 0;
}
  1. 提供单例对象的访问方法:静态成员函数
#include <iostream>
class A{
public:
//使用静态成员函数来提供唯一对象的访问方式,可以直接通过类名来直接访问静态成员函数,如果使用普通成员函数,只能使用对象来调用接口函数,但是违背类唯一对象的原则
	static A& getA(void){
		return m_a;
	}
private:
	static A m_a;
};
int main(){
	A::get();
	return 0;
}
  • 创建方式

饿汉式

单例对象无论用或者是不用,程序启动即创建
优点:代码实现简单,在多线程里是安全的,访问效率高
缺点:浪费内存

#include <iostream>
using namespace std;
class Singleton{
public:
    //提供公开的静态成员函数来获取唯一的对象
    static Singleton& getInstance(void){
        //返回值加上引用的作用是避免出现拷贝构造,在返回是避免出现临时对象
        return s_instance;
    }
private:
    //1.私有化构造函数包括拷贝构造
    Singleton(int data):m_data(data){
        cout<<"单例对象被创建啦"<<endl;
    }

    Singleton(const Singleton&);

    //2.使用静态成员变量来表示唯一的对象
    static Singleton s_instance;
private:
    int m_data;
};
Singleton Singleton::s_instance(123);

int main (void){
    cout << "main run" << endl;
    /*
    Singleton s1(123);
    //报错
     因为Singleton类的构造函数被定义为类私有成员函数,只有类的内部成员可以访问,在类的外部是访问不了的
     */
    //通过类中提供的共有函数来获取唯一对象的引用
    Singleton& s1 = Singleton::getInstance();
    Singleton& s2 = Singleton::getInstance();
    Singleton& s3 = Singleton::getInstance();
    /*
    Singleton s4 = s3;
    //error: ‘Singleton::Singleton(const Singleton&)’ is private within this context
    //   36 |     Singleton s4 = s3;
     //拷贝构造是私有的,在类的外部不能访问
     */
    cout<<"s1: "<<&s1<<endl;
    cout<<"s2: "<<&s2<<endl;
    cout<<"s3: "<<&s3<<endl;

}

运行结果

单例对象被创建啦
main run
s1: 0x557fe5f78154
s2: 0x557fe5f78154
s3: 0x557fe5f78154

进程已结束,退出代码 0

懒汉式

单例对象使用时在创建,不用即销毁
优点节省内存
缺点代码实现复杂
销毁时加入计数判断
多线程需要加互斥锁保护
效率较低

单例模式综合代码模板

#include <iostream>
#include <mutex>

using namespace std;
/*
 * 单例模式
 * 饿汉式(空间换时间)
 * 单例对象无论用或者不用,程序创建即启动
 * 懒汉式(时间换空间)
 * 单例对象用时在创建,不用即销毁
 */
//线程安全的懒汉单例模式
//程序需要时创建,程序不需要时即销毁
class lazySingleton {
private:
    //私有化构造函数和拷贝构造
    lazySingleton() {
        cout << "!!!create lazySingleton!!!" << endl;
    }

    lazySingleton(const lazySingleton &) = default;

    ~lazySingleton() {
        cout << "!!!~lazySingleton()!!!" << endl;
    }

    //使用静态指针来维护唯一的对象指针
    static lazySingleton *p;
    //互斥锁
    static pthread_mutex_t mutex;
    //单例对象使用个数
    static int count;
public:
    //单例对象指针的获取接口
    //仅仅第一次调用时会创建单例对象,多次调用将会得到相同的指针
    static lazySingleton *getSingleton();

    //单例对象释放接口
    //根据单例对象的使用数量来判断是否释放,仅仅当使用数为0时才会真正释放单例对象
    //当单例对象被真正释放时,计数值为零
    static int release();
};

//初始化单例对象指针,互斥锁,计数值
lazySingleton *lazySingleton::p = nullptr;
pthread_mutex_t lazySingleton::mutex = PTHREAD_MUTEX_INITIALIZER;
int lazySingleton::count = 0;

//获取单例对象指针接口实现
lazySingleton *lazySingleton::getSingleton() {
    //加锁
    //  这里使用了两个 if判断语句的技术称为双检锁;好处是,只有判断指针为空的时候才加锁,
    //  避免每次调用 GetInstance的方法都加锁,锁的开销毕竟还是有点大的。
    if (!p) {
        pthread_mutex_lock(&mutex);
        if (!p)
            p = new lazySingleton();
        //解锁
        pthread_mutex_unlock(&mutex);
        ++count;
    } else {
        ++count;
    }
    return p;
}

//单例对象释放接口
int lazySingleton::release() {
    //加锁
    //仅仅当p非NULL时才会进行加锁操作
    if (p) {
        pthread_mutex_lock(&mutex);
        if (--count == 0) {
            delete p;
            p = nullptr;
            std::cout << "delete lazy singleton" << std::endl;
        }
        //解锁
        pthread_mutex_unlock(&mutex);
    }
    return count;
}

//----------------------------------------------------------------
//饿汉
//程序创建即生成,程序销毁即释放
class hangrySingleton {
private:
    //私有化构造和拷贝构造
    hangrySingleton() {
        cout << "!!!create hangrySingleton!!!" << endl;
    }

    hangrySingleton(const hangrySingleton &) = default;

    ~hangrySingleton() {
        cout << "!!!~hangrySingleton()!!!" << endl;
    }

    static hangrySingleton *m_instancePoint;
public:
    static hangrySingleton *getSingleton();
};

hangrySingleton* hangrySingleton::m_instancePoint = new hangrySingleton();

hangrySingleton *hangrySingleton::getSingleton() {
    return m_instancePoint;
}

//-------------------------------------------------------------------
int main() {
    std::cout << "Code running" << std::endl;
    //通过类中提供的共有成员函数来获取单例对象
    hangrySingleton *hangryTest1 = hangrySingleton::getSingleton();
    lazySingleton *lazyTest1 = lazySingleton::getSingleton();
    cout << "first get\n"
            "hangry instance:" << hangryTest1 << endl <<
         "lazy instance:" << lazyTest1 << endl;

    hangrySingleton *hangryTest2 = hangrySingleton::getSingleton();
    lazySingleton *lazyTest2 = lazySingleton::getSingleton();
    cout << "second get\n"
            "hangry instance:" << hangryTest2 << endl <<
         "lazy instance:" << lazyTest2 << endl;

    hangrySingleton *hangryTest3 = hangrySingleton::getSingleton();
    lazySingleton *lazyTest3 = lazySingleton::getSingleton();
    cout << "three get\n"
            "hangry instance:" << hangryTest3 << endl <<
         "lazy instance:" << lazyTest3 << endl;
    if (hangryTest1 == hangryTest2 && hangryTest2 == hangryTest3)
        cout << "hangry test success" << endl;
    if (lazyTest1 == lazyTest2 && lazyTest2 == lazyTest3)
        cout << "lazy test success" << endl;


    cout << "first release\n"
            "singleton count :" << lazySingleton::release() << endl;
    cout << "second release\n"
            "singleton count :" << lazySingleton::release() << endl;
    cout << "three release\n"
            "singleton count :" << lazySingleton::release() << endl;

    return 0;
}

/home/panda/WorkSpace/Singleton/cmake-build-debug/Singleton
!!!create hangrySingleton!!!
Code running
!!!create lazySingleton!!!
first get
hangry instance:0x5607a8913eb0
lazy instance:0x5607a89142e0
second get
hangry instance:0x5607a8913eb0
lazy instance:0x5607a89142e0
three get
hangry instance:0x5607a8913eb0
lazy instance:0x5607a89142e0
hangry test success
lazy test success
first release
singleton count :2
second release
singleton count :1
three release
singleton count :!!!~lazySingleton()!!!
delete lazy singleton
0

进程已结束,退出代码 0
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值