文章目录
- 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; }//传引用 传值 传*_mptr
T* 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;
}