c++三种智能指针以及相关知识自写智能指针
Posted 头号理想
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c++三种智能指针以及相关知识自写智能指针相关的知识,希望对你有一定的参考价值。
传统指针存在的问题
当我们在堆上创建了一个对象的时候,如果我们用完,系统并不会回收资源,必须我们手动来释放它
如果我们没有处理好申请和释放的问题,那么可能造成内存泄漏的情况(没有释放/多次释放)
shared_ptr
每种指针都是以类模板的方式实现的,shared_ptr也不例外,
shared_ptr(T是指针指向的具体数据类型)的定义位于头文件,并且位于std命名空间中
#include<memory>
using namespace std;
和unique_ptr以及weak_ptr指针不同的地方在于:
多个shared_pt智能指针可以使用同一块堆内存,并且该类型只能指针在实现上采用的是引用计数机制
即使有一个shared_ptr放弃了堆内存的使用权 (引用计数减1) 也不会影响其他shared_ptr的使用 只有引用计数为0 堆内存才会释放
shared_ptr的创建
std::shared_ptr<int> p1;//不传入任何实参
std::shared_ptr<int> p2(nullptr);//传入空指针(c++11新特征)
std::shared_ptr<int> p3(new int(10));//明确指向
std::shared_ptr<int> p4 = std::make_shared<int>(10);//模板函数 c++11新特征
空的 shared_ptr 指针,其初始引用计数为 0,而不是 1。
同时 shared_ptr模板还提供了相应的构造函数和移动构造函数
std::shared_ptr<int> p5(p3);//调用拷贝构造函数
std::shared_ptr<int> p6(std::move(p4));//调用移动构造函数
同一指针不能同时为多个shared_ptr对象赋值,否则会导致程序发生异常
为了用户方便使用shared_ptr指针,shared_ptr模板类还提供了一些实用的成员方法
同时c++11新标准还支持同一类型的shared_ptr的对象货真shared_ptr之间进行== != >= <= > < 等的运算
实例
int main()
std::shared_ptr<int> p1(new int(10));
std::shared_ptr<int> p2(p1);
cout << "*p2" <<" "<< *p2 << endl;
p1.reset();//引用计数减1 p1成为空指针
if (p1)
cout << "p1不为空指针" << endl;
else
cout << "p1是空指针" << endl;
//以上操作不会影响p2
cout << "*p2" << " " << *p2 << endl;
cout << p2.use_count() << endl;
unique_ptr
unique_ptr也具备“在适当的时机自动释放堆内内存空间”的能力
和shared_ptr最大的不同之处就是在于 unique_ptr指针指向的堆内存无法将其与其他unique_str共享
也就是说unique_ptr指针都独自拥有对其所指堆内存空间的所有权
这也就是说 每个unique_str指针指向的堆内存空间的引用计数就是只能为1
一旦该unique_ptr指针放弃所致堆内存空间的所有权,该空间会被立即释放回收
unique_ptr和shared_ptr一样 模板类也提供了一些成员方法
实例
int main()
std::unique_ptr<int> p5(new int);
*p5 = 100;
int* p = p5.release();//释放当前对所指堆的使用权 但不会销毁存储空间
//p接收p5释放的堆内存
cout << "*p" << " " << *p << endl;
if (p5)
cout << "p5不为空" << endl;
else
cout << "p5为空" << endl;
std::unique_ptr<int> p6;
p6.reset(p);
//p6获取p的使用权 如果p为空 则p6也为空
cout << "*p6" << " " << *p6;
return 0;
weak_ptr
c++11虽然将weak_ptr指针定为智能指针的一种,但是该类型指针通常不单独使用(没有实际用处)
只能和share_ptr类型指针搭配使用,甚至我们将weak_ptr视为shared_ptr的一个辅助工具
借助weak_ptr指针我们可以获得shared_ptr指针的一些状态信息
比如有多少指向相同的shared_ptr指针,share_ptr指针指向的堆内存是否释放等等
同以上两个智能指针相同 weak_ptr也有很多成员方法
实例
int main()
std::shared_ptr<int> p1(new int(10));
std::shared_ptr<int> p2 = p1;
std::weak_ptr<int> p3(p2);
//输出和p3同志向的shared_ptr类型指针的数量
cout << p3.use_count() << endl;
p2.reset();//释放
cout << p3.use_count() << endl;
cout << *(p3.lock()) << endl;
//返回一个同指向shared_ptr的指针,获得他存储的数据
return 0;
以上就是c++11新特性中的三种智能指针
自写智能指针
当我们从对上申请了一个资源的时候,我们就创建一个智能指针对象,它指向这个资源
同时,在对上申请一个其计数作用的资源换,来统计后边所有共享该资源的对象的个数
假如将ptr1的对象赋值给ptr2 那么共享的计数就变为2
如果删除ptr2 引用计数就会减一
删除ptr1,引用计数就会变成0
一旦引用计数变成0 那么释放资源
准备工作:
智能指针对任何类型都可使用,所以他应该是一个模板
其次智能指针是一个类,可以使用构造函数和析构函数对引用计数进行操作
最后他要表现出指针的行为,使用起来像指针一样
template<class T>
class SharedPointer
public:
//默认构造函数,内部指针,未指向任何资源,引用计数为0,因为它未与任何资源绑定
SharedPointer() :m_refCount(nullptr), m_pointer(nullptr)
//构造函数,初始化时,指向一个已经分配好的资源
SharedPointer(T* adoptTarget) :m_refCount(nullptr), m_pointer(adoptTarget)
addReference();
//构造函数,使用其它对象创建新对象
SharedPointer(const SharedPointer<T>& copy)
:m_refCount(copy.m_refCount), m_pointer(copy.m_pointer)
addReference();
//析构函数,引用计数递减,当为0时,释放资源
virtual ~SharedPointer()
removeReference();
//赋值操作
//当左值被赋值时,表明它不再指向所指的资源,故引用计数减一
//之后,它指向了新的资源,所以对应这个资源的引用计数加一
SharedPointer<T>& operator=(const SharedPointer<T>& that)
if (this != &that)
removeReference();
this->m_pointer = that.m_pointer;
this->m_refCount = that.m_refCount;
addReference();
return *this;
//判断是否指向同一个资源
bool operator==(const SharedPointer<T>& other)
return m_pointer == other.m_pointer;
bool operator!=(const SharedPointer<T>& other)
return !operator==(other);
//指针解引用
T& operator*() const
return *m_pointer;
//调用所知对象的公共成员
T* operator->() const
return m_pointer;
//获取引用计数个数
int GetReferenceCount() const
if (m_refCount)
return *m_refCount;
else
return -1;
protected:
//当为nullpter时,创建引用计数资源,并初始化为1
//否则,引用计数加1。
void addReference()
if (m_refCount)
(*m_refCount)++;
else
m_refCount = new int(0);
*m_refCount = 1;
//引用计数减一,当变为0时,释放所有资源
void removeReference()
if (m_refCount)
(*m_refCount)--;
if (*m_refCount == 0)
delete m_refCount;
delete m_pointer;
m_refCount = 0;
m_pointer = 0;
private:
int* m_refCount;
T* m_pointer;
;
class MyClass
private:
int _id;
public :
~MyClass()
cout << "释放MyClass(" << _id << ")\\n";
MyClass(int i)
_id = i;
void Print()
cout << "MyClass(" << _id << ")" << endl;
;
int main()
MyClass* px = new MyClass(1);
SharedPointer<MyClass> ap(px);
SharedPointer<MyClass> bp = ap;
SharedPointer<MyClass> cp;
cout << "ap的引用个数:" << ap.GetReferenceCount() << endl;
cout << "将ap的值赋值给cp" << endl;
cp = ap;
cout << "ap的引用计数(3): "<< ap.GetReferenceCount() << endl;
MyClass* qx = new MyClass(5);
SharedPointer<MyClass> dp(qx);
ap = dp;
cout << "ap的引用计数(2): "
<< ap.GetReferenceCount() << endl;
cout << "dp的引用计数(2): "
<< dp.GetReferenceCount() << endl;
//"像指针一样使用智能指针"
dp->Print();
(*cp).Print();
希望我所写的对大家有帮助
以上是关于c++三种智能指针以及相关知识自写智能指针的主要内容,如果未能解决你的问题,请参考以下文章