5.5c++:shared_ptr使用场景,陷阱、性能分析,使用建议(转载)

shared_ptr使用场景

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

shared_ptr <int> create(int value)
{
    return make_shared<int> (value);//返回一个shared_ptr
}
//void myfunc(int value)
 shared_ptr<int> myfunc(int value)
 {
     shared_ptr<int> ptmp = create(10);
     //return;  //离开作用域之后,ptemp会被自动释放,它所指向的内存也会被自动释放。
     return ptmp; //系统是根据ptmp这个局部变量来产生一个临时的 shared_ptr对象返回返。
 }

int main()
{
    //shared_ptr的使用场景
    //myfunc(12); //如果这块不用shared_ptr变量来接收myfunc返回的结果,那么从myfunc返回额shared_ptr就会被销毁
    auto p11 = myfunc(12);//用一个 shared_ptr来接受,返回的就不会被销毁。
    return 0;
}

陷阱

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

void proc(shared_ptr<int> ptr)
{
    return ;
}

//class CT
//{
//public:
//    shared_ptr<CT> getself()
//    {
//        return shared_ptr<CT> (this);
//    }
//};
class CT:public enable_shared_from_this<CT>
{
    public:
    shared_ptr<CT> getself()
    {
        return shared_from_this();//这个就是通过此方法返回智能指针。
    }
};

class CB;//声明一下
class CA
{
public:
    shared_ptr<CB> m_pbs;
    
    ~CA()
    {
        int test;
        test = 1;
    }
};
class CB
{
public:
    //shared_ptr<CA> m_pas;
    weak_ptr<CA> m_pas;
    ~CB()
    {
        int test;
        test = 1;
    }
};

int main()
{
    //慎用裸指针
    int *p33 = new int(100);//裸指针
    //问题1:
    //proc(p33); //语法错误,不能使用裸指针传给shared_ptr

    //问题2:
    //proc(shared_ptr<int> (p));//参数是个 临时的shared_ptr,用一个裸指针显式的构造
    //*p = 45;
    //参数p传递给形参ptr之后,强引用的引用计数就是1,原来的裸指针指向的对象就汇编被销毁。
    //但是,出这个proc函数之后,引用计数就会变成0,此时再*p 就会出问题,因为它早就释放了。

    shared_ptr<int> p3(p33);//强引用计数为1
    proc(p3);//进入这个函数之后,强引用计数为2,再出来的时候,引用计数变为1.
    *p3 = 100;//此时,再赋值也没问题。
    // 把一个裸指针帮定到shared_ptr之后,内存管理的责任就到了shared_ptr那么 你就不能再用裸指针来访问这块内存了。

    //问题3:
    //不要用裸指针来初始化多个shared_ptr
    //绝对不可以,绝对不可以,绝对不可以

//    int *k = new int(122);
//    shared_ptr<int>kp(k);
//    shared_ptr<int>kp2(k);
//    cout << kp.get() <<endl;//地址相同,这样就会被释放2次,同一块内存,释放两次就会出错。
//    cout << kp2.get() <<endl;
//    cout<<kp.use_count()<<endl;//1
//    cout<<kp2.use_count()<<endl;//1

     //建议使用的方法
     shared_ptr<int> p1(new int);
     shared_ptr<int> p2(p1);//p1p2的控制块是互通的,可以解决上面的问题。

    //问题4:慎用get()返回的地址
    //返回智能指针指向的对应的裸指针。(有些函数接口可能只能使用裸指针)
    //(4.1)get返回的指针不能delete,否则异常。
//     shared_ptr<int> myp(new int(122));
//     int *p4 = myp.get();
//     // delete p;//不可以删除

    //(4.2)不能将其它智能指针绑到get返回的指针上。
//    shared_ptr<int> myp (new int(122));
//    int *p = myp.get();//这个指针千万不能随意释放。
//    {
//        shared_ptr<int> myp2(p);//myp 和 myp2引用计数都为1,一旦跳出程序块
//    }//离上面的作用范围,导致myp指向的内存被释放
//    *myp = 65; //该内存已经被释放,这样赋值会导致不可预料的后果。

      //问题(5):不要把类对象指针(this)作为shared_ptr返回。改用enable_shared_from_this;

      //没问题:
//       shared_ptr<CT> pct1(new CT);
//       shared_ptr<CT> pct2 = pct1;//这是两个强引用
       //有问题
//       shared_ptr<CT> pct1(new CT);
//       shared_ptr<CT> pct2 = pct1->getself();//问题出现 两个shared_ptr对象控制块不同,就会被释放两次


      //用到c++标准库里边的类模板 :enable_shared_from_this
        shared_ptr<CT> pct1(new CT);
        shared_ptr<CT> pct2 = pct1->getself();
        //enable_shared_from_this中有一个弱指针,weak_ptr能够监视this
        //在我们调用shared_from_this()这个方法的时候,这个方法内部实际上是调用了
        //weak_ptr的lock()方法,让shared_ptr指针计数加1,同时返回shared_ptr

      //问题(6):避免循环引用:能够导致内存泄露
//
//        shared_ptr<CA> pca(new CA);
//        shared_ptr<CB> pcb(new CB);
//        pca->m_pbs = pcb;//引用计数变为2,离开作用域之后还是1
//        pcb->m_pas = pca;//引用计数变为2,离开作用域之后还是1
        //最终都没调用析构函数。都泄露了。 
          
        //解决方法:就是把其中任何一个改成 弱引用,就可以了 
        shared_ptr<CA> pca(new CA);//1
        shared_ptr<CB> pcb(new CB);//1
        pca->m_pbs = pcb;//CB引用计数变为2
        pcb->m_pas = pca;  
        //因为是weak_ptr所以指向CA对象的只有一个强引用
        //离开作用域后,pca从1变道0,就会被释放。
        //导致CA内的m_pbs引用计数减1,最终都为0
        
} 



性能分析

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



int main()
{
    // 性能说明
    //(一)尺寸问题:
    //shared_ptr和weak_ptr 都是裸指针的两倍
    //控制块创建时机:
    //a)make_shared:分配并初始化一个对象,返回shared_ptr, 
    //b) 用裸指针来创建一个shared_ptr对象的时候。
    //  所以不允许用裸指针创建多个对象.强引用计数都为1.
    
    
    //(二)移动语句
    shared_ptr <int> p1 (new int(122));
    shared_ptr <int> p2 (std::move(p1));//移动语句 移动构造一个新的智能指针对象
                                        //p1就不再指向该对象(变成空),引用计数依旧是1
    shared_ptr<int> p3;
    p3 = sed::move(p2); //移动赋值,p2指向空,p3指向该对象,引用计数仍为1
    
    //移动肯定比复制快,复制需要增加引用计数,移动不需要
    //移动构造函数快过复制构造函数,移动赋值运算符快过拷贝赋值运算符。
} 
 


补充说明和使用建议

 //分配器
    //shared_ptr<int> p ((new , int) , mydelete(),myallocator<int>());
    
    //优先使用make_shared() //分配一次内存,尽管不能定义自己的删除器

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值