文章目录
- 1 设计模式
- 1.1 单例模式
- 1.1.1 懒汉单例
- 1.1.2 饿汉单例
- 1.1.3 总结
- 1.2 简单工厂模式
- 2 实现智能指针
1 设计模式
1.1 单例模式
某个类,不应该有多个实例,此时就可以使用单例模式。如果尝试创建多个实例,编译器就会报错。
1.1.1 懒汉单例
像一个懒汉一样,需要用到创建实例了程序再去创建实例,不需要创建实例程序就“懒得”去创建实例,这是一种时间换空间的做法,这体现了“懒汉的本性”。
使用懒汉模式来实现,Singleton类被加载的时候,不会立刻实例化,等到第一次使用这个实例的时候,再实例化。
#include <iostream>class Singleton {
public:static Singleton* getInstance() {cout << "SingleTon::getInstance()" << endl;if (instance == nullptr) {instance = new Singleton();}return instance;}private:static Singleton* instance;Singleton() {std::cout << "Singleton()" << std::endl;}Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;
};Singleton* Singleton::instance = nullptr; // 懒汉int main() {Singleton* singleton1 = Singleton::getInstance();Singleton* singleton2 = Singleton::getInstance();// 输出的实例地址相同,说明只有一个实例被创建std::cout << "singleton1 address: " << singleton1 << std::endl;std::cout << "singleton2 address: " << singleton2 << std::endl;return 0;
}
1.1.2 饿汉单例
像一个饿汉一样,不管需不需要用到实例都要去创建实例,即在类产生的时候就创建好实例,这是一种空间换时间的做法。
作为一个饿汉而言,体现了它的本质——“我全都要”。
简易写法
class Singleton {
private:static Singleton* instance; // 静态成员变量,存储唯一的实例// 私有构造函数,防止外部实例化Singleton() {}public:// 静态成员函数,用于获取实例static Singleton* getInstance() {return instance;}// 其他成员函数和成员变量
};// 初始化静态成员变量
Singleton* Singleton::instance = new Singleton();
或
#include <iostream>class SingleTon {
public:static SingleTon* getInstance() {cout << "SingleTon::getInstance()" << endl;return instance;}private:static SingleTon* instance;SingleTon() {std::cout << "SingleTon()" << std::endl;}SingleTon(const SingleTon&) = delete;SingleTon& operator=(const SingleTon&) = delete;
};// 在类外进行静态成员变量的定义和初始化
SingleTon* SingleTon::instance = new SingleTon();int main() {SingleTon* p1 = SingleTon::getInstance();SingleTon* p2 = SingleTon::getInstance();SingleTon* p3 = SingleTon::getInstance();// 在这里使用实例进行操作return 0;
}
Singleton 类通过一个静态成员变量 instance 存储唯一的实例。该实例在类加载时就被创建,并通过静态成员函数 getInstance() 返回。因为该实例在类加载时就创建,所以可以在任何时候通过 getInstance() 获取到同一个实例。
只要严格使用getInstance,就不会出现其他实例。
1.1.3 总结
懒汉式单例模式和饿汉式单例模式是两种常见的单例设计模式,它们的区别在于实例的创建时机和线程安全性。
1 创建时机:
懒汉式单例模式:在第一次使用时才创建实例。在 getInstance() 方法中进行判断,如果实例尚未创建,则创建一个实例并返回。懒汉式单例模式在程序启动时不会创建实例,而是在需要时才创建,也被称为延迟加载。
饿汉式单例模式:在类加载时就创建实例。在类的静态成员变量初始化时就创建了一个实例,并在 getInstance() 方法中直接返回该实例。饿汉式单例模式在程序启动时就会创建实例,无论是否被使用。
2 线程安全性:
懒汉式单例模式:默认情况下是线程不安全的。在多线程环境下,如果多个线程同时调用 getInstance() 方法并且实例尚未创建,则可能会创建多个实例。需要进行额外的线程安全措施,如加锁或使用双重检查锁定(Double-Checked Locking)来保证只有一个实例被创建。
饿汉式单例模式:默认情况下是线程安全的。在类加载时就创建了实例,所以不会存在多个线程同时创建实例的问题。无需额外的线程安全措施。
1.2 简单工厂模式
#include<iostream>
using namespace std;typedef enum Type {type1,type2
} Type;class product {
public:virtual void show() = 0;virtual ~product() = 0;
};
product::~product() {}class productA : public product{
public:void show() {cout << "productA" << endl;}~productA() override {cout << "~productA" << endl;}
};class productB : public product{
public:void show() override {cout << "productB" << endl;}~productB() override {cout << "~productB" << endl;}
};class Factory {
public:product *Create(enum Type type) {switch(type) {case type1:return new productA();case type2:return new productB();default:return nullptr;}}
};int main()
{Factory factory;factory.Create(type1)->show();factory.Create(type2)->show();return 0;
}
2 实现智能指针
C++11中提供了三种智能指针,使用这些智能指针时需要引用头文件<memory>
std::shared_ptr:共享的智能指针
采用引用计数的方法,允许多个智能指针指向同一个对象,指向该对象的所有智能指针内部的引用计数会加1,每减少一个智能指针指向对象时引用计数减一,当引用计数为0时自动析构
std::unique_ptr:独占的智能指针
std::unique_ptr是一个独占型的智能指针,它不允许其他的智能指针共享其内部的指针,可以通过它的构造函数初始化一个独占智能指针对象,但是不允许通过赋值将一个unique_ptr赋值给另一个unique_ptr。
std::weak_ptr:弱引用的智能指针,它不共享指针,不能操作资源,是用来监视shared_ptr的。
弱引用智能指针std::weak_ptr可以看做是shared_ptr的助手,它不管理shared_ptr内部的指针。std::weak_ptr没有重载操作符*和->,因为它不共享指针,不能操作资源,所以它的构造不会增加引用计数,析构也不会减少引用计数,它的主要作用就是作为一个旁观者监视shared_ptr中管理的资源是否存在。
共享指针详解
实现智能指针:
利用栈上的对象出作用域自动析构的特征,采用了栈上面的指针去管理堆上面的内容
//不带引用计数智能指针
#include <iostream>using namespace std;template<typename T>
class SmartPtr {
public:SmartPtr(T* ptr = nullptr) : _mptr(ptr) {}~SmartPtr() { delete _mptr; }T& operator*() { return *_mptr; }//传引用 传值 传*_mptrT* operator->() { return _mptr; }//传指针 传_mptr;
private:T* _mptr;
};class Test {
public:void test() { cout << "call Test::test" << endl; }
};int main() {SmartPtr<int> ptr1(new int);*ptr1 = 20;cout << *ptr1 << endl;SmartPtr<Test> ptr2(new Test());ptr2->test();return 0;
}
带引用计数智能指针
//带引用计数智能指针
#include <iostream>
#include <memory.h>using namespace std;template<typename T>
class RefCnt
{
public:RefCnt(T *ptr = nullptr):mptr (ptr){if (mptr != nullptr)mcount = 1;}void addRef(){ mcount++; }//增加引用计数int delRef(){ return --mcount;}//减少引用计数
private :T *mptr;int mcount;
};template<typename T>
class Csmartptr
{
public:Csmartptr(T* ptr = nullptr) :mptr(ptr) {mpRefCnt = new RefCnt<T>(mptr);}/*Csmartptr(const Csmartptr<T> &src){mptr = new T(*src .mptr) ;}*/~Csmartptr() { if (0 == mpRefCnt->delRef () ){delete mptr; mptr = nullptr;}}T& operator*() { return *mptr; }T* operator->() {return mptr; }Csmartptr(const Csmartptr<T> &src):mptr(src.mptr), mpRefCnt(src.mpRefCnt){if (mptr != nullptr)mpRefCnt->addRef() ;}Csmartptr<T>& operator= (const Csmartptr<T> &src){if (this == &src)return *this;//删除原有对象指向的资源if (0 == mpRefCnt->delRef () ){delete mptr;}mptr = src.mptr;mpRefCnt = src.mpRefCnt ;mpRefCnt->addRef () ;return *this;}private:T* mptr;//指向资源的指针RefCnt<T> *mpRefCnt;//指向该资源引用计数对象的指针
};int main() {Csmartptr<int> ptr1 (new int) ;Csmartptr<int> ptr2(ptr1) ;Csmartptr<int> ptr3;ptr3 = ptr2;*ptr1 = 20;cout << *ptr2 << " " << *ptr3 << endl ;system("pause");return 0;
}