现在推广网站最好的方式,临沂网站制作方案,我要做网站推广,国内搜索引擎1.智能指针的使用及原理
1.1 RAII
RAII#xff08;Resource Acquisition Is Initialization#xff09;是一种利用对象生命周期来控制程序资源#xff08;如内 存、文件句柄、网络连接、互斥量等等#xff09;的简单技术。
在对象构造时获取资源#xff0c;接着控制对资…1.智能指针的使用及原理
1.1 RAII
RAIIResource Acquisition Is Initialization是一种利用对象生命周期来控制程序资源如内 存、文件句柄、网络连接、互斥量等等的简单技术。
在对象构造时获取资源接着控制对资源的访问使之在对象的生命周期内始终保持有效最后在对象析构的时候释放资源。借此我们实际上把管理一份资源的责任托管给了一个对象。 这种做法有两大好处 1.不需要显式地释放资源。 2.采用这种方式对象所需的资源在其生命期内始终保持有效。 // 使用RAII思想设计的SmartPtr类
templateclass T
class SmartPtr {
public:SmartPtr(T* ptr nullptr): _ptr(ptr){}~SmartPtr(){if(_ptr)delete _ptr;}private:T* _ptr;
};
int div()
{int a, b;cin a b;if (b 0)throw invalid_argument(除0错误);return a / b;
}
void Func()
{ShardPtrint sp1(new int);ShardPtrint sp2(new int);cout div() endl;
}
int main()
{try {Func();}catch(const exception e){coute.what()endl;}return 0;
}
1.2 智能指针的原理
上述的SmartPtr还不能将其称为智能指针因为它还不具有指针的行为。指针可以解引用也可 以通过-去访问所指空间中的内容因此AutoPtr模板类中还得需要将* 、-重载下才可让其 像指针一样去使用。
templateclass T
class SmartPtr {
public:
SmartPtr(T* ptr nullptr): _ptr(ptr){}
~SmartPtr(){if(_ptr)delete _ptr;}
T operator*() {return *_ptr;}
T* operator-() {return _ptr;}
private:
T* _ptr;
};
struct Date
{int _year;int _month;int _day;
};
int main()
{
SmartPtrint sp1(new int);
*sp1 10
cout*sp1endl;
SmartPtrint sparray(new Date);
// 需要注意的是这里应该是sparray.operator-()-_year 2018;
// 本来应该是sparray--_year这里语法上为了可读性省略了一个-
sparray-_year 2018;
sparray-_month 1;
sparray-_day 1;
} 总结一下智能指针的原理 1. RAII特性 2. 重载operator*和opertaor-具有像指针一样的行为 1.3 std::auto_ptr
C98版本的库中就提供了auto_ptr的智能指针。下面演示的auto_ptr的使用及问题。 auto_ptr的实现原理管理权转移的思想下面简化模拟实现了一份bit::auto_ptr来了解它的原理
// C98 管理权转移 auto_ptr
namespace bit
{templateclass Tclass auto_ptr{public:auto_ptr(T* ptr):_ptr(ptr){}auto_ptr(auto_ptrT sp):_ptr(sp._ptr){// 管理权转移sp._ptr nullptr;}auto_ptrT operator(auto_ptrT ap){// 检测是否为自己给自己赋值if (this ! ap){// 释放当前对象中资源if (_ptr)delete _ptr;// 转移ap中资源到当前对象中_ptr ap._ptr;ap._ptr NULL;}return *this;}~auto_ptr(){if (_ptr){cout delete: _ptr endl;delete _ptr;
}}// 像指针一样使用T operator*(){return *_ptr;}T* operator-(){return _ptr;}private:T* _ptr;};
}
// 结论auto_ptr是一个失败设计很多公司明确要求不能使用auto_ptr
//int main()
//{
// std::auto_ptrint sp1(new int);
// std::auto_ptrint sp2(sp1); // 管理权转移
//
// // sp1悬空
// *sp2 10;
// cout *sp2 endl;
// cout *sp1 endl;
// return 0;
//}
1.4 std::unique_ptr
C11中开始提供更靠谱的unique_ptr
unique_ptr的实现原理简单粗暴的防拷贝下面简化模拟实现了一份UniquePtr来了解它的原 理
// C11库才更新智能指针实现
// C11出来之前boost搞除了更好用的scoped_ptr/shared_ptr/weak_ptr
// C11将boost库中智能指针精华部分吸收了过来
// C11-unique_ptr/shared_ptr/weak_ptr
// unique_ptr/scoped_ptr
// 原理简单粗暴 -- 防拷贝
namespace bit
{templateclass Tclass unique_ptr{public:unique_ptr(T* ptr):_ptr(ptr){}~unique_ptr()
{if (_ptr){cout delete: _ptr endl;delete _ptr;}}// 像指针一样使用T operator*(){return *_ptr;}T* operator-(){return _ptr;}unique_ptr(const unique_ptrT sp) delete;unique_ptrT operator(const unique_ptrT sp) delete;private:T* _ptr;};
}
//int main()
//{
// /*bit::unique_ptrint sp1(new int);
// bit::unique_ptrint sp2(sp1);*/
//
// std::unique_ptrint sp1(new int);
// //std::unique_ptrint sp2(sp1);
//
// return 0;
//}
1.5 std::shared_ptr
C11中开始提供更靠谱的并且支持拷贝的shared_ptr
shared_ptr的原理是通过引用计数的方式来实现多个shared_ptr对象之间共享资源。 1. shared_ptr在其内部给每个资源都维护了着一份计数用来记录该份资源被几个对象共 享。 2. 在对象被销毁时(也就是析构函数调用)就说明自己不使用该资源了对象的引用计数减 一。 3. 如果引用计数是0就说明自己是最后一个使用该资源的对象必须释放该资源 4. 如果不是0就说明除了自己还有其他对象在使用该份资源不能释放该资源否则其他对象就成野指针了。 // 引用计数支持多个拷贝管理同一个资源最后一个析构对象释放资源
namespace bit
{templateclass Tclass shared_ptr{public:shared_ptr(T* ptr nullptr):_ptr(ptr), _pRefCount(new int(1)), _pmtx(new mutex){}shared_ptr(const shared_ptrT sp):_ptr(sp._ptr), _pRefCount(sp._pRefCount), _pmtx(sp._pmtx){AddRef();}void Release(){_pmtx-lock();bool flag false;if (--(*_pRefCount) 0 _ptr){cout delete: _ptr endl;delete _ptr;delete _pRefCount;flag true;}_pmtx-unlock();if (flag true){delete _pmtx;}}void AddRef(){_pmtx-lock();(*_pRefCount);_pmtx-unlock();}shared_ptrT operator(const shared_ptrT sp){//if (this ! sp)if (_ptr ! sp._ptr){Release();
_ptr sp._ptr;_pRefCount sp._pRefCount;_pmtx sp._pmtx;AddRef();}return *this;}int use_count(){return *_pRefCount;}~shared_ptr(){Release();}// 像指针一样使用T operator*(){return *_ptr;}T* operator-(){return _ptr;}T* get() const{return _ptr;}private:T* _ptr;int* _pRefCount;mutex* _pmtx;};// 简化版本的weak_ptr实现templateclass Tclass weak_ptr{public:weak_ptr():_ptr(nullptr){}weak_ptr(const shared_ptrT sp):_ptr(sp.get()){}weak_ptrT operator(const shared_ptrT sp){_ptr sp.get();return *this;
}T operator*(){return *_ptr;}T* operator-(){return _ptr;}private:T* _ptr;};
}shared_ptr智能指针是线程安全的吗 是的引用计数的加减是加锁保护的。但是指向资源不是线程安全的 指向堆上资源的线程安全问题是访问的人处理的智能指针不管也管不了 引用计数的线程安全问题是智能指针要处理的 std::shared_ptr的线程安全问题通过下面的程序我们来测试shared_ptr的线程安全问题。需要注意的是shared_ptr的线程安全分为两方面
1. 智能指针对象中引用计数是多个智能指针对象共享的两个线程中智能指针的引用计数同时 或--这个操作不是原子的引用计数原来是1了两次可能还是2.这样引用计数就错 乱了。会导致资源未释放或者程序崩溃的问题。所以只能指针中引用计数、--是需要加锁 的也就是说引用计数的操作是线程安全的。
2. 智能指针管理的对象存放在堆上两个线程中同时去访问会导致线程安全问题。 2.C11和boost中智能指针的关系
C11和boost中智能指针的关系
1. C 98 中产生了第一个智能指针auto_ptr.
2. C boost给出了更实用的scoped_ptr和shared_ptr和weak_ptr.
3. C TR1引入了shared_ptr等。不过注意的是TR1并不是标准版。
4. C 11引入了unique_ptr和shared_ptr和weak_ptr。需要注意的是unique_ptr对应boost 的scoped_ptr。并且这些智能指针的实现原理是参考boost中的实现的。