一、思路与流程
想要实现一个C++ shared_ptr智能指针类,首先先要回顾C++中提供的shared_ptr有哪些接口,以及实现了哪些功能,将需求全部列出来后再逐一击破。
- 智能指针的构造方法
1)默认构造,例如:shared_ptr<int> p1;
默认初始化的智能指针保存的是一个空指针。
2)有参构造,例如:shared_ptr<int> p1(ptr2);
其中ptr2是一个int*类型的指针,但不建议使用普通指针初始化智能指针。
3)拷贝构造,例如:shared_ptr<int> p2(sptr1);
其中sptr1是一个shared_ptr类型的对象。
4)移动构造,例如:shared_ptr<int> p2(std::move(sptr1));
其中sptr1是一个shared_ptr类型的对象。如果使用移动构造函数,智能指针的计数值不会增加,相当于资源从智能指针sptr1转移到了智能指针p2中。
此外可以采用make_shared函数构造智能指针,这部分超出要实现的智能指针类之外,暂不考虑。
- 赋值运算符
shared_ptr的拷贝运算既支持左值运算又支持右值运算,测试如下:
// 用左值类型进行赋值操作
shared_ptr<int> p1 = make_shared<int>(10);
shared_ptr<int> p2 = p1;
cout << p2.use_count() << endl; //2 引用计数为2
// 用右值类型进行赋值操作
shared_ptr<int> p1 = make_shared<int>(10);
shared_ptr<int> p2 = std::move(p1);
cout << p2.use_count() << endl; //1 引用计数为1
- 智能指针的其他操作
成员函数 | 功能 |
---|---|
p.get() | 返回智能指针中保存的普通指针 |
p.use_count() | 返回shared_ptr智能指针p中引用计数值 |
p.unique() | 智能指针中计数值是否为1,是则返回true,否则返回false |
p2.swap(p1) | 交换智能指针p1和智能指针p2中的指针 |
二、代码实现
class shared_count{
public:
shared_count():m_count(1){}
~shared_count() = default;
void AddCount(){++m_count;}
long GetCount(){return m_count;}
long ReduceCount(){return --m_count;}
private:
long m_count;
};
template <typename T>
class Shared_ptr{
public:
//默认/有参构造函数
Shared_ptr(T* ptr = nullptr):m_ptr(ptr){
if(ptr){
ref_count = new shared_count();
}
}
~Shared_ptr(){
if(m_ptr && !ref_count -> ReduceCount()){
//释放构造函数中创建的堆区内存
delete m_ptr;
delete ref_count;
}
}
//拷贝构造函数
Shared_ptr(Shared_ptr<T>& sptr){
m_ptr = sptr.m_ptr;
if(m_ptr){
ref_count = sptr.ref_count;
ref_count -> AddCount();
}
}
//移动构造函数
Shared_ptr(Shared_ptr<T>&& sptr){
m_ptr = sptr.m_ptr;
if(m_ptr){
ref_count = sptr.ref_count;
sptr.m_ptr = nullptr;
sptr.m_count = nullptr;
}
}
//赋值运算符
Shared_ptr& operator=(Shared_ptr& sptr){
m_ptr = sptr.m_ptr;
if(m_ptr){
ref_count = sptr.ref_count;
ref_count -> AddCount();
}
return *this;
}
Shared_ptr& operator=(Shared_ptr<T>&& sptr){
m_ptr = sptr.m_ptr;
if(m_ptr){
ref_count = sptr.ref_count;
sptr.m_ptr = nullptr;
sptr.ref_count = nullptr;
}
return *this;
}
// 指针特性运算符重载
T* operator ->(){
return m_ptr;
}
T& operator *(){
return *m_ptr;
}
//get函数
T* get(){return m_ptr;}
//use_count函数
long use_count(){
if(m_ptr){
return ref_count -> GetCount();
}
return 0;
}
//unique函数
bool unique(){
if(m_ptr && ref_count -> GetCount() == 1)
return true;
return false;
}
//swap函数
void swap(Shared_ptr<T>& sptr){
swap(m_ptr, sptr.m_ptr);
swap(ref_count,sptr.ref_count);
}
private:
T* m_ptr;
shared_count* ref_count;
};
三、功能测试
- 默认构造函数
Shared_ptr<int> sptr1;
cout << "sptr1.use_count() = " << sptr1.use_count() << endl; //0
- 与new结合进行初始化
Shared_ptr<int> sptr2(new int(10));
cout << "sptr2.use_count() = " << sptr2.use_count() << endl; //1
- 拷贝构造初始化
Shared_ptr<int> sptr2(new int(10));
Shared_ptr<int> sptr3(sptr2);
cout << "sptr3.use_count() = " << sptr3.use_count() << endl; //2
- 移动构造初始化
Shared_ptr<int> sptr2(new int(10));
Shared_ptr<int> sptr4(std::move(sptr2));
cout << "sptr4.use_count() = " << sptr4.use_count() << endl; //1
- 拷贝复制运算符
Shared_ptr<int> sptr2(new int(10));
Shared_ptr<int> sptr5 = sptr2;
cout << "sptr5.use_count() = " << sptr5.use_count() << endl; //2
- 移动拷贝运算符
Shared_ptr<int> sptr2(new int(10));
Shared_ptr<int> sptr6 = std::move(sptr2);
cout << "sptr6.use_count() = " << sptr6.use_count() << endl; //1
- 指针运算符
//*操作符
Shared_ptr<int> sptr2(new int(10));
cout << *sptr2 << endl; //10
// ->操作符
```cpp
Shared_ptr<string> sptr7(new string("olivia"));
cout << sptr7 -> size() << endl; //6
参考文章:
https://blog.csdn.net/readyone/article/details/111596876
https://blog.csdn.net/PX1525813502/article/details/124914944