C++11智能指针shared_ptr

文章介绍了智能指针shared_ptr在C++中的使用,强调了其引用计数如何影响对象的生命周期。通过示例展示了当多个shared_ptr指向同一对象时,引用计数如何增加和减少。还讨论了当智能指针之间存在循环引用时可能导致的内存泄露问题,以及如何利用weak_ptr来解决这个问题。

智能指针shared_ptr引用计数

#include <iostream>
#include <memory>
#include <vector>
#include <cstring>
using namespace std;

class City
{
public:
   string name;
   City(string m_name)
   {
       this->name = m_name;
       cout << "name = " << name <<endl;
       cout<<"调用构造函数~City("<<name<<")析构。\n";
   }

   ~City()
   {
       cout<<"调用析构函数~City("<<name<<")析构。\n";
   }
};

int main()
{
    shared_ptr<City> p0(new City("shanghai"));
    shared_ptr<City> p = p0;
    shared_ptr<City> p1 = p0;
    
    shared_ptr<City> q0(new City("beijing"));
    shared_ptr<City> q1 = q0;
    shared_ptr<City> q2= q0;

    cout << "p0.use_count() = " << p0.use_count()<< endl;
    cout << "q2.use_count() = " << q2.use_count()<< endl;

    return 0;
}

//输出:
name = shanghai
调用构造函数~City(shanghai)析构。
name = beijing
调用构造函数~City(beijing)析构。
p0.use_count() = 3
q2.use_count() = 3
调用析构函数~City(beijing)析构。
调用析构函数~City(shanghai)析构。

shaped_ptr支持普通的拷贝和赋值,左边的shaped_ptr引用计数+1,右边的shaped_ptr引用计数-1。当shaped_ptr的引用计数为0时,就会调用析构函数,释放资源。

#include <iostream>
#include <memory>
using namespace std;

class City
{    
public:
   string name;
   City(string m_name)
   {
    name = m_name;
    cout <<"构造 City = "<< name << endl;
   }
   ~City()
   {
    cout << "析构 City = "<< name << endl;
   }

};

int main() 
{
    shared_ptr<City> p0 (new City("nanjing"));
    shared_ptr<City> p1 = p0;
    shared_ptr<City> p2 = p1;

    shared_ptr<City> q0 (new City("hangzhou"));
    shared_ptr<City> q1 = q0;
    shared_ptr<City> q2 = q1;
    cout << "原始记录: " << endl;
    cout <<"p0.use_count() = " << p0.use_count() << endl;
    cout << "q0.use_count() = " << q0.use_count() << endl;

    q1 = p0;
    cout << "q1 = p0之后: " << endl;
    cout <<"p0.use_count() = " << p0.use_count() << endl;
    cout << "q0.use_count() = " << q0.use_count() << endl;
    
    q2 = p1;
    cout << "q2 = p1之后: " << endl;
    cout <<"p0.use_count() = " << p0.use_count() << endl;
    cout << "q0.use_count() = " << q0.use_count() << endl;
    
    cout << "q0 = p2之前: " << endl;
    q0 = p2;
    cout << "q0 = p2之后: " << endl;
    cout <<"p0.use_count() = " << p0.use_count() << endl;
    cout << "q0.use_count() = " << q2.use_count() << endl;
    
    return 0;
    
//输出:
构造 City = nanjing
构造 City = hangzhou
原始记录:
p0.use_count() = 3
q0.use_count() = 3
q1 = p0之后:
p0.use_count() = 4
q0.use_count() = 2
q2 = p1之后:
p0.use_count() = 5
q0.use_count() = 1
q0 = p2之前:
析构 City = hangzhou
q0 = p2之后:
p0.use_count() = 6
q0.use_count() = 6
析构 City = nanjing
}

shaped_ptr相互引用,造成引用计数无法为0,会造成内存泄露,这时引入了weak_ptr,解决shaped_ptr相互引用计数,解决了内存泄露问题。

shaped_ptr循环引用计数参考代码:

#include <iostream>
#include <memory>
using namespace std;

class A;
class B;

class A
{
public:
    A()
    {
        cout << "A 构造函数" << endl;
    }
    ~A()
    {
        cout << "A 析构函数" << endl;
    }
    shared_ptr<B> ptr;
};

class B
{
public:
    B()
    {
        cout << "B 构造函数" << endl;
    }
    ~B()
    {
        cout << "B 析构函数" << endl;
    }
    shared_ptr<A> ptr;
};

int main()
{
    shared_ptr<A> pa(new A());   //A对象的引用计数ref=1
    shared_ptr<B> pb(new B());   //B对象的引用计数ref=1
    pa->ptr = pb;    //B对象的引用计数ref=2
    pb->ptr = pa;    //A对象的引用计数ref=2
        
    cout << "pa.use_count() = " << pa.use_count() <<endl;
    cout << "pb.use_count() = "<< pb.use_count() << endl;
     //离开作用域后,虽然pa和pb智能指针对象释放了,但由于其所指对象的引用计数为1而未被释放,故造成内存泄漏。
    
    return 0;
     /*
     *首先创建的时候双方的引用计数为1,接着pb赋值给pa->ptr_b这个会使pb的引用计数加1,
     此时为2,pa仍为1,接着pa赋值给pb->ptr_a这个由于是weak_ptr指针的构造,
     不会使它的引用计数加1,pa的引用计数为1,pb的引用计数为2,离开作用域后,pa计数为0,析构,pb计数为2-1=1,不析构,
     但是由于pa析构,pa中的ptr_b会析构,那么引用计数减1,这时候pb引用计数为1-1=0,也析构。实现资源的完整释放。
     */
}
//输出:
A 构造函数
B 构造函数
pa.use_count() = 2
pb.use_count() = 2

weak_ptr解决循环引用计数参考代码:

#include <iostream>
#include <memory>
using namespace std;

class A;
class B;

class A
{
public:
    A()
    {
        cout << "A 构造函数" << endl;
    }
    ~A()
    {
        cout << "A 析构函数" << endl;
    }
    shared_ptr<B> ptr;
};

class B
{
public:
    B()
    {
        cout << "B 构造函数" << endl;
    }
    ~B()
    {
        cout << "B 析构函数" << endl;
    }
    weak_ptr<A> ptr;
};

int main()
{
    shared_ptr<A> pa(new A());   //A对象的引用计数ref=1
    shared_ptr<B> pb(new B());   //B对象的引用计数ref=1
    pa->ptr = pb;    //B对象的引用计数ref=2
    pb->ptr = pa;    //A对象的引用计数ref=2
        
    cout << "pa.use_count() = " << pa.use_count() <<endl;
    cout << "pb.use_count() = "<< pb.use_count() << endl;
     //离开作用域后,虽然pa和pb智能指针对象释放了,但由于其所指对象的引用计数为1而未被释放,故造成内存泄漏。
    
    return 0;
     /*
     *首先创建的时候双方的引用计数为1,接着pb赋值给pa->ptr_b这个会使pb的引用计数加1,
     此时为2,pa仍为1,接着pa赋值给pb->ptr_a这个由于是weak_ptr指针的构造,
     不会使它的引用计数加1,pa的引用计数为1,pb的引用计数为2,离开作用域后,pa计数为0,析构,pb计数为2-1=1,不析构,
     但是由于pa析构,pa中的ptr_b会析构,那么引用计数减1,这时候pb引用计数为1-1=0,也析构。实现资源的完整释放。
     */
}

//输出:
A 构造函数
B 构造函数
pa.use_count() = 1
pb.use_count() = 2
A 析构函数
B 析构函数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值