C++ 智能指针 atuo_ptr,unique_ptr,shared_ptr,weak_ptr

本文详细介绍了C++中的智能指针,包括`auto_ptr`的废弃与`unique_ptr`的安全性,`shared_ptr`的引用计数机制及可能导致的循环引用问题,以及`weak_ptr`如何解决循环引用。示例代码展示了各种智能指针的使用场景和效果,并通过对比说明了它们之间的区别。
摘要由CSDN通过智能技术生成
#include <bits/stdc++.h>
#include <memory>//智能指针头文件
using namespace std;
int main(){
    /*
    1.auto_ptr 已经被C++11废弃了,所有权模式,
    当两个auto_ptr 指针指向同一个地址时,
    当一个指针释放内存时,
    另外一个指针还是指向这个地址,
    并且可以这个指针访问,但是会导致程序崩溃
    auto_ptr建议改用uniqu_ptr
    */
    auto_ptr<int> p1(new int(10));
    cout<<"p1指向的地址的内容 "<<*p1<<endl;
    auto_ptr<int> p2 = p1;//编译器支持这种写法,p2剥夺p1的所有权,但是p1依然可以访问,会导致崩溃
    //cout<<*p1<<endl;




    /*
    2.unique_ptr 不支持赋值操作,更安全
    可以使用move函数进行所有权变更
    */
    unique_ptr<int> p3(new int(11));
    cout<<"p3指向的地址的内容 "<<*p3<<endl;
    //unique_ptr<int> p4 = p3; //编译器不支持这种写法,但可以使用move
    unique_ptr<int> p4 = move(p3);
    cout<<"p3指向的地址 "<<p3.get()<<endl; //置为NULL了
    cout<<"p4指向的地址的内容 "<<*p4<<endl;

    /*
    3.shared_ptr 共享机制,
    对于指向的那个地址有一个引用计数(use_count方法可以查看),
    当引用计数为0时才释放指向的内存
    但存在一个bug:
    当两个对象同时使用一个shared_ptr成员变量指向对方,
    会造成循环引用,使引用计数失效,从而导致内存泄露
    */
    shared_ptr<int> p5(new int(12));
    shared_ptr<int> p6 = p5;cout<<"p6指向的地址的内容 "<<*p6<<endl;
    shared_ptr<int> p7 = p6;cout<<"p7指向的地址的内容 "<<*p7<<endl;
    cout<<"p5指向的地址引用数 "<<p5.use_count()<<endl;//引用数
    cout<<"p5指向的地址 "<<p5.get()<<endl;//p5指向的地址
    cout<<"p6指向的地址 "<<p6.get()<<endl;//p6指向的地址
    cout<<"p7指向的地址 "<<p7.get()<<endl;//p7指向的地址,同一个地址
    p7.reset();//引用数减1
    cout<<"p5指向的地址引用数 "<<p5.use_count()<<endl;//引用数
    cout<<"p5指向的地址的内容 "<<*p5<<endl;
    p6.reset();//引用数减1
    p5.reset();//引用数减1
    cout<<"p5指向的地址引用数 "<<p5.use_count()<<endl;//引用数
    cout<<"p5指向的地址 "<<p5.get()<<endl;//引用数为0,指向的空间释放了,指向了NULL


    /*
    4.weak_ptr
    进行该对象的内存管理的是那个强引用的 shared_ptr。
    weak_ptr只是提供了对管理对象的一个访问手段。
    只能由一个shared_ptr或另外一个weak_ptr对weak_ptr进行初始化
    它的构造和析构不会引起引用记数的增加或减少。
    不能通过weak_ptr直接访问对象的方法,需要先转换为转化为shared_ptr
    通过调用lock函数来获得shared_ptr
    weak_ptr本身也是一个模板类,
    但是不能直接用它来定义一个智能指针的对象,
    只能配合shared_ptr来使用,
    可以将shared_ptr的对象赋值给weak_ptr,
    并且这样并不会改变引用计数的值。
    查看weak_ptr的代码时发现,
    它主要有lock、swap、reset、expired、operator=、use_count几个函数,
    与shared_ptr相比多了lock、expired函数,
    但是却少了get函数,甚至连operator* 和 operator->都没有
    */
    shared_ptr<int> p8(new int(13));
    cout<<"p8指向的地址引用数 "<<p8.use_count()<<endl;//引用数
    weak_ptr<int> p9(p8); //不改变引用数目
    cout<<"p8指向的地址引用数 "<<p8.use_count()<<endl;//引用数
    //cout<<*p9<<endl;//没有对weak_ptr进行*的重载,无法取到指向的地址的值,需要先转换成shared_ptr
    cout<<"p9指向的地址的内容 "<<*(p9.lock())<<endl; //使用lock()方法获取shared_ptr
    return 0;
}

运行结果:
在这里插入图片描述

weak_ptr在类中的使用,解决shared_ptr循环引用问题

#include <bits/stdc++.h>
#include <memory>//智能指针头文件
using namespace std;
class TestShared{
public:
    char name;
    shared_ptr<TestShared> p;
    TestShared(char value){
        name = value;
        cout<<"TestShared 构造函数被调用"<<endl;
    }
    ~TestShared(){
        cout<<"TestShared对象"<<name<<"的析构函数被调用"<<endl;
        p.reset();
    }
};
class TestWeak{
public:
    char name;
    weak_ptr<TestWeak> p;
    TestWeak(char value){
        name = value;
        cout<<"TestWeak 构造函数被调用"<<endl;
    }
    ~TestWeak(){
        cout<<"TestWeak对象"<<name<<"的析构函数被调用"<<endl;
        p.reset();
    }
};
void testSharePtr(){
    shared_ptr<TestShared> p1(new TestShared('a')), p2(new TestShared('b'));
    //循环引用,造成内存泄露
    cout<<"p1指向的地址引用数 "<<p1.use_count()<<endl;
    cout<<"p2指向的地址引用数 "<<p2.use_count()<<endl;
    p1->p = p2;
    p2->p = p1;
    cout<<"p1指向的地址引用数 "<<p1.use_count()<<endl;
    cout<<"p2指向的地址引用数 "<<p2.use_count()<<endl;
    cout<<"程序结束"<<endl;
    return ;
}
void testWeakPtr(){
    shared_ptr<TestWeak> p1(new TestWeak('a')), p2(new TestWeak('b'));
    //正常析构
    cout<<"p1指向的地址引用数 "<<p1.use_count()<<endl;
    cout<<"p2指向的地址引用数 "<<p2.use_count()<<endl;
    p1->p = p2;
    p2->p = p1;
    cout<<"p1指向的地址引用数 "<<p1.use_count()<<endl;
    cout<<"p2指向的地址引用数 "<<p2.use_count()<<endl;
    cout<<"程序结束"<<endl;
    return ;
}
int main(){
    testSharePtr();
    cout<<"--------------------------"<<endl;
    testWeakPtr();
    return 0;
}

运行结果:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值