茶叶网站建设,抖音关键词排名软件,免费推广网站入口2023燕,安卓手机app开发用什么软件智能指针原理
智能指针基本上就是利用 RAII 技术实现的。资源取得时机便是初始化时机#xff08;Resource Acquisition Is Initialization#xff09;是一种利用对象生命周期来控制程序资源的技术。在对象构造时获取资源#xff0c;接着控制对资源的访问#xff0c;使之在…智能指针原理
智能指针基本上就是利用 RAII 技术实现的。资源取得时机便是初始化时机Resource Acquisition Is Initialization是一种利用对象生命周期来控制程序资源的技术。在对象构造时获取资源接着控制对资源的访问使之在对象的生命周期内始终保持有效最后在对象析构的时候释放资源。
智能指针的实现要考虑的问题
怎么实现 RAII如何重载 operator* 和 opertaor-怎么复制智能指针对象
前两个问题比较简单本文就不多做赘述了。下文主要介绍如何正确实现 shared_ptr 的复制函数。
shared_ptr
shared_ptr 这种智能指针访问对象采用共享所有权来管理其生存期。没有哪个特定的 shared_ptr 拥有该对象。取而代之的是所有指涉到它的 shared_ptr 共同协作确保在不再需要该对象的时刻将其析构。当最后一个指涉到某对象的 shared_ptr 不再指涉到它时该 shared_ptr 会析构其指涉到的对象。
因此需要知道有多少个 shared_ptr 指向同一个资源。我们可以用一个引用计数该计数在构造的时候初始化复制的时候只需要将该值加 1 即可。经复制得到的对象共享同一个引用计数。 用 static int 实现引用计数可以吗 既然我们需要多个对象共享同一个引用计数那使用静态变量可以吗
这是不行的使用静态变量是可以做到共享但静态变量在整个类中只有一个。也就是说我们定义出的所有对象共享同一个计数这明显是不行的。 用 int 实现引用计数可以吗 很明显不可以。当我们用复制一个 shared_ptr 类型对象时我们获取到的是 int 类型的值两个对象没有任何关联。 那用指针实现引用计数可以吗 这是可以的。
假如我们用 int* 实现计数。在构造函数中我们为指针 new 一块空间并初始化为 1表示有一个 shared_ptr 指向该对象。在复制构造函数中我们直接复制指针的值这样两个指针指向的实际是同一块空间将指向的空间的值加 1 即可。
上面这样在多线程情况下会有问题因此我们需要用一些方式来保护对临界资源的访问。下面分别用互斥锁和原子变量两种方式实现。
互斥锁
#include iostream
#include mutex
using namespace std;templateclass T
class SharedPtr {public:SharedPtr(T* ptr) : _data(ptr),_cnt(new int(1)),_mtx(new mutex) {cout 构造函数 endl;} ~SharedPtr() {bool deleteFlag false;_mtx-lock();if ((*_cnt)-- 1) {delete _data;delete _cnt;deleteFlag true;}_mtx-unlock();if (deleteFlag) {cout 析构函数 endl;delete _mtx;}}SharedPtr(const SharedPtrT sp) : _data(sp._data),_cnt(sp._cnt),_mtx(sp._mtx) {_mtx-lock();(*_cnt);_mtx-unlock();}SharedPtrT operator(const SharedPtrT sp) {SharedPtrT tmp sp;Swap(tmp);return *this;}private:void Swap(SharedPtrT other) {std::swap(_data, other._data);std::swap(_cnt, other._cnt);std::swap(_mtx, other._mtx);}private:T* _data;int* _cnt;mutex* _mtx;
};int main() {SharedPtrint sp1(new int(10));SharedPtrint sp2(sp1);SharedPtrint sp3(new int(1));sp3 sp2;return 0;
}原子变量
在上面的实现方式中我们用了互斥锁来保护计数以实现原子性的加减。我们也可以直接用 C 提供的原子类型变量。
#include atomic
#include iostream
using namespace std;class RefCnt {public:RefCnt(): _cnt(1) {}int AddRef() {return _cnt;}int SubRef() {return --_cnt;}private:atomicint _cnt;
};templateclass T
class SharedPtr {public:SharedPtr(T* ptr) : _data(ptr),_refCnt(new RefCnt) {cout 构造函数 endl;}~SharedPtr() {if (_refCnt-SubRef() 0) {delete _data;delete _refCnt;cout 析构函数 endl;}}SharedPtr(const SharedPtrT sp) : _data(sp._data),_refCnt(sp._refCnt) {_refCnt-AddRef();}SharedPtrT operator(const SharedPtrT sp) {SharedPtrT tmp sp;Swap(tmp);return *this;}private:void Swap(SharedPtrT other) {std::swap(_data, other._data);std::swap(_refCnt, other._refCnt);}private:T* _data;RefCnt* _refCnt;
};int main() {SharedPtrint sp1(new int(10));SharedPtrint sp2(sp1);SharedPtrint sp3(new int(1));sp3 sp2;return 0;
}代码比起使用互斥锁的方法简单了不少。