C++智能指针

  C++在使用new创建一个对象后,如果不使用delete释放的话,可能会造成内存的泄露。因此C++设计了智能指针,可以自动的释放内存。常见的有:
shared_ptr:允许多个指针指向同一个对象。
unique_ptr:指针独占一个对象。
weak_ptr:弱指针。
使用智能指针的时候,要包含头文件#include< memory>

shared_ptr

  shared_ptr存在一个计数功能。每当一个指针指向同一个对象时,计数就会加1。每删除一个指针,计数就会减1。当计数为0时,就会释放内存(对于new\delete一般在构造函数中new,在析构函数中delete)。

#include <iostream>
#include <memory>
using namespace std;
void calcul_num(shared_ptr<int> i)
{
    (*i)++;
}
int main()
{
    shared_ptr<int> a = make_shared<int>(10);
    calcul_num(a);
    cout<<*a<<endl;  // 输出为11
}

  可以使用get获得原始指针,使用use_count查找一个对象的使用次数。

#include <iostream>
#include <memory>
using namespace std;
int main()
{
    int temp = 10;
    shared_ptr<int> a1 = make_shared<int>(temp);
    shared_ptr<int> a2 = a1;
    shared_ptr<int> a3 = a1;
    int* p = a2.get();
    // a1,a2,a3共用一片内存,修改a1的值,a2也会跟着变化
    *a1 = 100;
    cout<<*a2<<endl;
    // 输出为3  3  3
    cout<<a1.use_count()<<"  "<<a2.use_count()<<"  "<<a3.use_count()<<endl;
    a1.reset();  //释放a1
    // 输出为0  2  2
    cout<<a1.use_count()<<"  "<<a2.use_count()<<"  "<<a3.use_count()<<endl;
    a2.reset();  //释放a2
    // 输出为0  0  1
    cout<<a1.use_count()<<"  "<<a2.use_count()<<"  "<<a3.use_count()<<endl;
    
    // 智能指针+new开辟内存
    shared_ptr<string> sp(new string("hellow"));
    shared_ptr<string> sp2 = sp;
    cout<<sp.use_count()<<endl;
    cout<<*sp<<endl;
}
#include <iostream>
#include <memory>
using namespace std;
struct ListNode
{
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
    ListNode(){}
};
int main(int argc,char* argv[])
{
    ListNode* ln = new ListNode(100);
    shared_ptr<ListNode*> node = make_shared<ListNode*>(ln);
    (*node)->val = 10;
    cout<<(*node)->val<<endl;
    cout<<node.use_count()<<endl;
}

unique_ptr

  unique_ptr指针禁止和其他指针共用一个对象。因此当unique_ptr销毁时,其指向的对象也会被销毁。
  unique_ptr只能使用new来进行初始化,不支持普通拷贝和赋值。

#include <iostream>
#include <memory>
using namespace std;
int main()
{
    // unique_ptr只能使用new来进行赋值
    unique_ptr<int> a1(new int(10));
    // 错误,unique_ptr不支持拷贝
    // unique_ptr<int> a2(a1);
    // 错误,unique_ptr不允许多个指针指向同一个对象
    // unique_ptr<int> a2 = a1;
}

可以使用move实现unique_ptr的转移

#include <iostream>
#include <memory>
using namespace std;
int main()
{
    // unique_ptr只能使用new来进行赋值
    unique_ptr<int> a1(new int(10));
    // 将a1移动给a2,此时a1被释放。
    unique_ptr<int> a2 = move(a1);
    // unique_ptr<int> a2(move(a1));
    // 错误,此时a1已经被释放了
    // cout<<*a1<<endl;
    // 输出为10
    cout<<*a2<<endl;
}

weak_ptr

  弱指针,绑定到一个shared_ptr对象,不会改变shared_ptr的引用计数。当最后一个shared_ptr指针被销毁后,其所指向的对象就会被释放。此时即使有weak_ptr指针指向该对象,依旧会被释放。

#include <iostream>
#include <memory>
using namespace std;
int main()
{
    weak_ptr<int> wp;
    {
        shared_ptr<int> w = make_shared<int>(10);
        wp = w;
        // 输出为1,可见weak_ptr并没有改变shared_ptr的指向对象的引用次数。
        cout<<wp.use_count()<<endl;
    }
    // 输出为0
    cout<<wp.use_count()<<endl;
}

验证:

在这里插入图片描述

#include <iostream>
#include <memory>
#include <string>
using namespace std;
void test_weak_ptr(weak_ptr<string>& wp)
{
    if(shared_ptr<string> sp = wp.lock())
        cout<<"weak_ptr不为空"<<endl;
    else
        cout<<"weak_ptr为空"<<endl;
    if(!wp.expired())
    {
        shared_ptr<string> sp = wp.lock();
        cout<<"对象为"<<*sp<<endl;
    }
}
int main()
{
    shared_ptr<string> sp = make_shared<string>("hellow world");
    // 创建一个弱引用指向sp。
    weak_ptr<string> wp1(sp);
    weak_ptr<string> wp2(sp);
    // 此时wp1不为空。
    test_weak_ptr(wp1);
    // 此时sp指向的对象释放掉,wp1变为空。
    sp.reset();
    test_weak_ptr(wp1);
}
//weak_ptr不为空
//对象为hellow world
//weak_ptr为空

需要注意的是,弱指针reset()之后,并不会释放对象的内存。

#include <iostream>
#include <memory>
#include <string>
using namespace std;
void test_weak_ptr(weak_ptr<string>& wp)
{
    if(shared_ptr<string> sp = wp.lock())
        cout<<"weak_ptr不为空"<<endl;
    else
        cout<<"weak_ptr为空"<<endl;
    if(!wp.expired())
    {
        shared_ptr<string> sp = wp.lock();
        cout<<"对象为"<<*sp<<endl;
    }
}
int main()
{
    shared_ptr<string> sp = make_shared<string>("hellow world");
    // 创建一个弱引用指向sp。
    weak_ptr<string> wp1(sp);
    weak_ptr<string> wp2(sp);
    wp1.reset();
    test_weak_ptr(wp2);
}

//weak_ptr不为空
//对象为hellow world

weak_ptr解决的问题

在这里插入图片描述  当创建智能指针spA,spB时,计数+1。当shared_ptr类型的spA、spB对象析构时,ref_count 减一;由于Obj A 和 Obj B中的shared_ptr智能指针还相互引用,导致ref_count不为零,spA和spB不会去析构所指的对象,最终导致内存泄漏。

#include <iostream>
#include <memory>
#include <string>
using namespace std;
class A;
class B;
class A
{
public:
    shared_ptr<B> ObjA;
};
class B
{
public:
    shared_ptr<A> ObjB;
};
int main()
{
    weak_ptr<A> temp_A;
    weak_ptr<B> temp_B;

    shared_ptr<A> spA = make_shared<A>();
    shared_ptr<B> spB = make_shared<B>();
    spA->ObjA = spB;
    spB->ObjB = spA;

    temp_A = spA;
    temp_B = spB;
    spA.reset();
    spB.reset();

    cout<<"spA次数:"<<temp_A.use_count()<<endl;
    cout<<"spB次数:"<<temp_B.use_count()<<endl;
}
// 输出为
// spA次数:1
// spB次数:1
// 可见内存没有被释放,存在内存泄露

将类中的shared_ptr改为weak_ptr,此时类间的相互引用为弱指针,不算入计数次数中。

#include <iostream>
#include <memory>
#include <string>
using namespace std;
class A;
class B;
class A
{
public:
    weak_ptr<B> ObjA;
};
class B
{
public:
    weak_ptr<A> ObjB;
};
int main()
{
    weak_ptr<A> temp_A;
    weak_ptr<B> temp_B;

    shared_ptr<A> spA = make_shared<A>();
    shared_ptr<B> spB = make_shared<B>();
    spA->ObjA = spB;
    spB->ObjB = spA;

    temp_A = spA;
    temp_B = spB;
    spA.reset();
    spB.reset();

    cout<<"spA次数:"<<temp_A.use_count()<<endl;
    cout<<"spB次数:"<<temp_B.use_count()<<endl;
}
// 输出为
// spA次数:0
// spB次数:0
// 可见内存被释放
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值