shared_ptr 简介:
shared_ptr 是 C++ 标准库中的一种智能指针,它实现了共享所有权的内存管理,可以让多个智能指针同时管理同一个对象。shared_ptr 通过引用计数的方式来管理内存,即每个 shared_ptr 对象都会维护一个引用计数器,记录有多少个 shared_ptr 对象指向同一个对象。
shared_ptr.h简单实现智能指针的一些接口,下面是测试结果
#include "shared_ptr.h"
#include <iostream>
using namespace std;
class Ball{
public:
Ball(){
cout<<"a ball haved create"<<endl;
}
~Ball(){
cout<<"a ball haved destroy"<<endl;
}
void Bolls(){
cout << "a ball is fetched"<<endl;
}
};
int main(){
//创建一个指向Ball的智能指针对象p1
shared_ptr<Ball>p1{ new Ball() };
//Ball对象只有一个智能指针指向,所以应该输出1
cout << p1.use_count() << endl;
//创建一个指向Ball的智能指针对象p2
shared_ptr<Ball>p2(p1);
//Ball对象有两个智能指针指向,所以应该输出2
cout <<p1.use_count()<<" " << p2.use_count()<<endl;
return 0;
}
运行结果
a ball haved create
1
2 2
a ball haved destroy
shared_ptr.h实现
我们首先定义两个类私有成员原始指针(ptr_)和引用计数(ref_count_)
private:
//原始指针
T* ptr_;
//引用计数
size_t* ref_count_;
类构造函数,如果初始化了ptr,即指向了对象,我们的引用计数初始化为1
测试用例的shared_ptr<Ball>p1{ new Ball() };就调用了下面的构造函数,语句ptr指向Ball对象
shared_ptr(T* ptr = nullptr) {
if (ptr) {
ref_count_ = new size_t(1);
ptr_ = ptr;
}
}
执行第一条语句后指针指向
拷贝构造函数,语句shared_ptr<Ball>p2(p1);使用的就是拷贝构造函数,将参数p1的东西赋值给p2对象,并让引用计数器加1
shared_ptr(const shared_ptr<T>& other) {
ptr_ = other.ptr_;
ref_count_ = other.ref_count_;
if (ref_count_) {
++(*ref_count_);
}
}
执行语句shared_ptr<Ball>p2(p1)后的指针指向
可以看到每创建一个智能指针对象指向同一个对象时,计数器ref_count_就会加1,这个是shared_ptr的核心。
shared_ptr智能指针对象在离开作用域后就会调用析构函数,--(*ref_count_) == 0 语句判断是否只有自己一个指针指向对象,即引用计数减1后是否为0,如果是,我们就释放掉指针指向的资源,即对象资源。
~shared_ptr() {
if (ref_count_ && --(*ref_count_) == 0) {
//释放掉指向的资源
delete ptr_;
delete ref_count_;
}
}
重载赋值运算符
shared_ptr<T>& operator=(const shared_ptr<T>& other) {
if (this != &other) {
ptr_ = other.ptr_;
ref_count_ = other.ref_count_;
if (ref_count_) {
++(*ref_count_);
}
}
return *this;
}
获取计数器
size_t use_count() const {
return ref_count_ ? *ref_count_ : 0;
}
完整代码
#include <cstddef>
template <typename T>
class shared_ptr{
public:
//构造函数
shared_ptr(T* ptr = nullptr) {
if (ptr) {
ref_count_ = new size_t(1);
ptr_ = ptr;
}
}
shared_ptr(const shared_ptr<T>& other) {
ptr_ = other.ptr_;
ref_count_ = other.ref_count_;
if (ref_count_) {
++(*ref_count_);
}
}
~shared_ptr() {
if (ref_count_ && --(*ref_count_) == 0) {
delete ptr_;
delete ref_count_;
}
}
shared_ptr<T>& operator=(const shared_ptr<T>& other) {
if (this != &other) {
ptr_ = other.ptr_;
ref_count_ = other.ref_count_;
if (ref_count_) {
++(*ref_count_);
}
}
return *this;
}
T& operator*() const {
return *ptr_;
}
T* operator->() const {
return ptr_;
}
operator bool() const {
return ptr_;
}
//获取原始指针
T* get() const{
return ptr_;
}
//获取计数器
size_t use_count() const {
return ref_count_ ? *ref_count_ : 0;
}
private:
//原始指针
T* ptr_;
//引用计数
size_t* ref_count_;
};
后面就添加一些接口,可以自己实现,如果代码有问题,欢迎提出意见。