当前位置: 首页 > article >正文

智能指针中的share_ptr(共享智能指针)

初始化

共享智能指针是指多个智能指针可以同时管理同一块有效的内存,共享智能指针 share_ptr 是一个模板类,如果进行初始化有三种方式如下:
  1. 通过构造函数初始化
  2. std::make shared 辅助函数
  3. reset方法
共享智能指针对象初始化完毕之后就指向了要管理的那块堆区内存,如果想要查看当前有多少个智能指针同时管理着这块内存可以使用共享智能指针提供的一个成员函数use_count。
构造函数初始化
//使用智能指针管理一块 int 型的堆内存
shared_ptr<int> ptrl(new int(520));
cout<<"ptr1管理的内存引用计数:"<<ptr1.use_count()<< endl;
//使用智能指针管理一块字符数组对应的堆内存
shared_ptr<char> ptr2(new char[520]);
cout<<"ptr2 管理的内存引用计数:"<<ptr2.use_count()<<endl;
shared_ptr<int> ptr3;
cout<<"ptr3 管理的内存引用计数:"<<ptr3.use count()<<endl;
// 创建智能指针对象,初始化为空
shared_ptr<int> ptr4(nullptr);
cout<<"ptr4管理的内存引用计数:"<<ptr4.use count()<< endl;
/*打印结果如下:
ptr1 管理的内存引用计数:1
ptr2 管理的内存引用计数:1
ptr3 管理的内存引用计数:0
ptr4 管理的内存引用计数:0*/
/*如果智能指针被初始化了一块有效内存,那么这块内存的引用计数+1,
如果智能指针没有被初始化或者被初始化为 nullptr 空指针,引用计数为 0。
另外,不要使用一个原始指针初始化多个shared_ptr。*/
#include <iostream>
#include <memory>
using namespace std;
int main() {
    int* raw_ptr = new int(10);
    shared_ptr<int> sp1(raw_ptr);
    shared_ptr<int> sp2(raw_ptr);
    // 在这里,sp1和sp2各自维护自己的引用计数,它们不知道彼此的存在
    // 当sp1的引用计数归零时,它会释放raw_ptr指向的内存
    // 但是此时sp2还在使用这个内存,这就会导致错误,二次释放问题
    return 0;
}
拷贝和移动构造函数初始化

当一个智能指针被初始化之后,就可以通过这个智能指针初始化其他新对象。在创建新对象的时候,对应的拷贝构造函数或者移动构造函数就被调用了

//构造函数
shared_ptr<int> ptrl(new int(520));
cout<<"ptr1 管理的内存引用计数:"<<ptrl.use count()<< endl;

//拷贝构造函数
shared_ptr<int> ptr2(ptrl);
cout<<"ptr2 管理的内存引用计数:"<<ptr2.use count()<< endl;
shared_ptr<int>ptr3=ptrl;
cout <<"ptr3 管理的内存引用计数:"<<ptr3.use count()<<endl;

//移动构造函数
//移动构造会把ptr1的资源移动到ptr4,ptr1会变成一个空指针,不在管理原来的资源,所以引用计数不增加
shared_ptr<int>ptr4(std::move(ptrl));
cout<<"ptr4管理的内存引用计数:"<<ptr4.use count()<< endl;
std::shared_ptr<int>ptr5=std::move(ptr2);
cout<<"ptr5 管理的内存引用计数:"<< ptr5.use count()<<endl;

/*打印结果如下:
ptr1管理的内存引用计数:1
ptr2管理的内存引用计数:2
ptr3管理的内存引用计数:3
ptr4管理的内存引用计数:3
ptr5管理的内存引用计数:3*/
std::make shared 初始化

通过 c++11 提供的 std::make shared()就可以完成内存对象的创建并将其初始化给智能指针

#include <iostream>
#include <string>
#include <memory>
using namespace std;
class Test{
public:
    Test(){
        cout<< "无参构造函数"<< endl;
    }
    Test(int x){
        cout<<"int 类型构造函数"<< x<< endl;
    }
    Test(string str){
        cout <<"string 类型的构造函数"<<str<< endl;
    }
    ~Test(){
        cout<<"析构函数"<< endl;
    }
};
int main(){
// 使用智能指针管理一块 int 型的堆内存,内部引用计数为 1
    shared_ptr<int>ptrl=make shared<int>(520);
    cout<<"ptr1管理的内存引用计数:"<<ptr1.use_count()<< endl;
    shared_ptr<Test>ptr2=make shared<Test>();
    cout<<"ptr2 管理的内存引用计数:"<<ptr2.use_count()<< endl;
    shared_ptr<Test>ptr3 =make shared<Test>(520);
    cout<<"ptr3 管理的内存引用计数:"<<ptr3.use_count()<< endl;
    shared_ptr<Test>ptr4 = make shared<Test>("QQQQ");
    cout<<"ptr4管理的内存引用计数:"<<ptr4.use_count()<< endl;
    shared_ptr<Test>ptr5(new Test(200));
    cout<<"ptr5 的引用计数为:"<<ptr5.use_count()<< endl;
    return 0;
}

/*打印结果如下:
    ptr1管理的内存引用计数:1
    无参构造函数
    ptr2管理的内存引用计数:1
    int类型构造函数 520
    ptr3管理的内存引用计数:1
    string类型的构造函数 QQ22
    ptr4管理的内存引用计数:1
    int类型构造函数
    ptr5管理的内存引用计数:1
    析构函数
    析构函数
    析构函数
    析构函数*/

如果使用拷贝的方式初始化共享智能指针,这两个对象会同时管理同一块内存,堆内存对应的引用技术也会增加。如果使用移动构造的方式初始化智能指针对象,只是转让了内存的所有权,管理内存的对象不会增加,因此内存引用技术不会增加。

reset方法初始化
#include <iostream>
#include <string>
#include <memory)
using namespace std;
int main(){
// 使用智能指针管理一块 int 型的堆内存,内部引用计数为 1
    shared_ptr<int>ptrl=make shared<int>(520);
    shared_ptr<int>ptr2=ptrl;
    shared_ptr<int> ptr3=ptrl;
    shared_ptr<int>ptr4=ptrl;
    cout<<"ptr1 管理的内存引用计数:"<< ptrl.use count()<< endl;
    cout<<"ptr2 管理的内存引用计数:"<<ptr2.use count()<< endl;
    cout<<"ptr3 管理的内存引用计数:"<<ptr3.use count()<< endl;
    cout<<"ptr4管理的内存引用计数:"<<ptr4.use count()<< endl;
    ptr4.reset();
    cout<<"ptr1 管理的内存引用计数:"<< ptrl.use count()<< endl;
    cout<<"ptr2 管理的内存引用计数:"<<ptr2.use count()<< endl;
    cout<<"ptr3 管理的内存引用计数:"<<ptr3.use count()<< endl;
    cout<<"ptr4管理的内存引用计数:"<<ptr4.use count()<< endl;
    shared ptr<int> ptr5;
    ptr5.reset(new int(250));
    cout<<"ptr5 管理的内存引用计数:"<<ptr5.use count()<< endl;
    return 0;
}

/*打印结果如下
    ptr1管理的内存引用计数:4
    ptr2 管理的内存引用计数:4
    ptr3 管理的内存引用计数:4
    ptr4 管理的内存引用计数:4
    ptr1 管理的内存引用计数:3
    ptr2 管理的内存引用计数:3
    ptr3 管理的内存引用计数:3
    ptr4 管理的内存引用计数:0
    ptr5 管理的内存引用计数:1*/

对于一个未初始化的共享智能指针,可以通过 reset 方法来初始化,当智能指针中有值得时候,调用reset 会使引用计数减 1.

获取原始指针

get()函数

nt main(){
    shared_ptr<int> p(new int);
    *p = 100;
    cout << *p.get()<<" "<< *p<< endl;
    return 0

}
//100 100
share_ptr实现
#pragma once
#include<iostream>
using namespace std;

template<typename T>
class Ref
{
T* p;
    int n;
public:
    Ref() {
p = nullptr;
n = 0;
    }
    Ref(T* p) {
this->p = p;
n = 1;
    }
    void increase() {
if(p) n++;
    }
    void reduce() {
if(n>0) n--;
if (n == 0) {
delete p;
delete this;
}
    }
    int useCount() {
return n;
    }
T* get() {
return p;
}
};

template<typename T>
class Shared_ptr
{
Ref<T>* r;
public:
    Shared_ptr() {
r = new Ref<T>();
    }
    Shared_ptr(T* p) {
r = new Ref<T>(p);
    }
    Shared_ptr(const Shared_ptr& o) {
this->r = o.r;
if(r->get()) r->increase();
    }
    Shared_ptr(Shared_ptr&& o) {
this->r = o.r;
o.r = nullptr;
    }
    ~Shared_ptr() {
if(r) r->reduce();
    }
Shared_ptr& operator=(const Shared_ptr& other) {
r->reduce();
this->r = other.r;
if(r->get()) this->r->increase();
return *this;
    }
Shared_ptr operator=(Shared_ptr&& other) {
r->reduce();
this->r = other.r;
other.r = nullptr;
return *this;
    }
    int use_Count() {
if (r) return r->useCount();
else return 0;
    }
T* get() {
return r->get();
    }
void reset() {
r->reduce();
r = nullptr;

    }
    void reset(T* p) {
r->reduce();
r = new Ref<T>(p);

    }
T& operator*() {
return *(r->get());
    }
T* operator->() {
return r->get();
    }
};


http://www.kler.cn/a/429713.html

相关文章:

  • PCB印刷电路板快速上手04电容元件
  • 【大模型入门指南 07】量化技术浅析
  • RocketMQ 知识速览
  • 智慧公厕大数据驱动下的公共卫生管理与优化
  • 快速、可靠且高性价比的定制IP模式提升芯片设计公司竞争力
  • Web开发(一)HTML5
  • 使用ffmpeg将视频与字幕合并为一个文件并将视频拼接
  • 永磁同步电机负载估计--线性扩张状态观测器
  • 分离轴定理检测两个凸多边形是否相交
  • AI驱动的低代码平台:解密背后的算法与架构创新
  • STC单片机I2C驱动例程
  • psmisc移植到ARM Linux环境
  • 【EthIf编译脚本】communication/EthIf/EthIf.mod.mk
  • 夜莺运维指南之自定义告警模板
  • C/C++流星雨
  • 使用php生成、识别二维码
  • ElasticSearch如何做性能优化?
  • Online Monocular Lane Mapping
  • vba学习系列(9)--按需求计数单元格数量
  • vue之$emit 获取返回值
  • 数字孪生与大型模型强强联合,共塑工业制造崭新前景
  • .NET用C#导入Excel数据到数据库
  • 面试技术点之安卓篇
  • 游戏AI实现-有限状态机
  • 通过Zynq FPGA对雷龙SD NAND进行测试
  • 黑马商城docker部署部分MySQL拉取超时解决方法