带引用计数的智能指针的实现
智能指针的原理
智能指针是一个类,这个类的构造函数中传入一个普通指针,析构函数中释放传入的指针。智能指针的类都是栈上的对象,所以当函数(或程序)结束时会自动被释放。
常用的智能指针
unique_ptr,一个智能指针独占一块内存资源,其生命周期从 unique_ptr 指针创建时开始,直到离开作用域。离开作用域时,若其指向对象,则将其所指对象销毁。不支持复制和赋值,直接赋值会编译出错。实在想赋值的话,需要使用:std::move。
1 | |
shared_ptr,基于引用计数的智能指针。可随意赋值,直到内存的引用计数为0的时候这个内存会被释放。
weak_ptr,弱引用。 引用计数有一个问题就是互相引用形成环,这样两个指针指向的内存都无法释放。需要手动打破循环引用或使用weak_ptr。顾名思义,weak_ptr是一个弱引用,只引用,不计数。如果一块内存被shared_ptr和weak_ptr同时引用,当所有shared_ptr析构了之后,不管还有没有weak_ptr引用该内存,内存也会被释放。所以weak_ptr不保证它指向的内存一定是有效的,在使用之前需要检查weak_ptr是否为空指针。
智能指针的实现
C++中智能指针的实现主要依赖于两个技术:
1、析构函数,对象被销毁时会被调用的一个函数,对于基于栈的对象而言,如果对象离开其作用域则对象会被自动销毁,而此时析构函数也自动会被调用。
2、引用计数技术,维护一个计数器用于追踪资源(如内存)的被引用数,当资源被引用时,计数器值加1,当资源被解引用时,计算器值减1。
3、操作符重载,智能指针的大致实现原理就是在析构函数中,检查所引用对象的引用计数,如果引用计数为0,则真正释放该对象内存。
实现带引用计数的智能指针
1、接收不同对象类型的构造函数
这个构造函数实现,比较简单,直接将引用计数+1即可。
2、析构函数
析构函数的实现,不能直接做 delete 操作,而是需要先对引用计数 -1,当引用计数为 0 时,才做 delete 操作。
3、拷贝构造函数
拷贝构造函数的实现,底层指针共享,然后将引用计数 +1 即可。
4、赋值操作符
赋值操作符的实现,稍微复杂一些,涉及到将新指向对象的引用计数 +1,将原指向对象的引用计数 -1,如果有需要还要销毁原指向对象。
为了能够使用引用计数技术,我们的智能指针不能再像原生指针那样能用可以指向任意资源对象,我们的智能指针只能指向实现了存在方法 incRefCount 和方法 decRefCount 的资源类了。
我们需要重载*运算符和->运算符:
我们使用指针最终还是需要通过指针去访问其所指向的资源对象的数据及方法,这个过程称为指针的解引用过程。指针的解引用可以使用*运算符和->运算符;
1 | |
1 | |