shared_ptr介绍
1.裸指针直接初始化,但不能通过隐式转换来构造
2.允许移动构造,也允许拷贝构造
3.通过make_shared构造
实现一个shared_ptr
需要考虑以下几点:
● 构造函数中计数初始化为1;
● 拷贝构造函数中计数值加1;
● 赋值运算符中,左边的对象引用计数减1,右边的对象引用计数加1;
● 析构函数中引用计数减1;
● 在赋值运算符和析构函数中,如果减1后为0,则调用delete释放对象。
#include<iostream>
using namespace std;
template<typename T>
class SharedPtr {
public:
SharedPtr(T* ptr = NULL) :_ptr(ptr), _pcount(new int(1)) {}
SharedPtr(const SharedPtr<T>& sp) :_ptr(sp._ptr), _pcount(sp._pcount) {
(*_pcount)++; //每次构造一个对象,计算就加1
}
SharedPtr<T>& operator=(const SharedPtr<T>& sp) { //赋值指针计数
*(sp._pcount)++;
if (--(*_pcount) == 0) {
delete _ptr;
_ptr = nullptr; //防止悬空指针
delete _pcount;
_pcount = nullptr;
}
_ptr = sp._ptr;
_pcount = sp._pcount;
return *this;
}
// 获取引用计数
int use_count() {
return *_pcount;
}
T& operator*() { return *_ptr; } //重载*
T* operator->() { return _ptr; }
~SharedPtr() { //自动释放资源,防止内存泄露
--(*_pcount);
if (*_pcount == 0) {
delete _ptr;
_ptr = nullptr;
delete _pcount;
_pcount = nullptr;
}
}
private:
T* _ptr;
int* _pcount; //引用计数
};
int main() {
SharedPtr<int> myp(new int(5));
int icount = myp.use_count(); // 某个对象有几个智能指针指向
cout << "myp = " << icount << endl; // 输出1
{
SharedPtr<int> myp2(myp); //拷贝构造函数
icount = myp2.use_count();
cout << "myp2 = " << icount << endl; // 输出2
}
icount = myp.use_count(); // 输出1。因为出了作用域,myp2不在存在。
cout << "myp = " << icount << endl; //1
return 0;
}