• 智能指针注意的坑


    1.同一普通指针不能同时为多个 shared_ptr 对象赋值,否则会导致程序发生异常。例如:

    int* ptr = new int;
    std::shared_ptr<int> p1(ptr);
    std::shared_ptr<int> p2(ptr);//错误. 容易引起double delete

    原因是这个地址容易引起 double delete 懂的吧

    2 在初始化 shared_ptr 智能指针时,还可以自定义所指堆内存的释放规则,这样当堆内存的引用计数为 0 时,会优先调用我们自定义的释放规则。
    在某些场景中,自定义释放规则是很有必要的。比如,对于申请的动态数组来说,shared_ptr 指针默认的释放规则是不支持释放数组的,只能自定义对应的释放规则,才能正确地释放申请的堆内存。

    //指定 default_delete 作为释放规则 
    std::shared_ptr<int> p6(new int[10], std::default_delete<int[]>());
    对于申请的动态数组,释放规则可以使用 C++11 标准中提供的 default_delete<T> 模板类外,我们也可以自定义释放规则:如下
    //自定义释放规则 void deleteInt(int*p) { //也可以写成lamd 表达式 delete []p; } //初始化智能指针,并自定义释放规则 std::shared_ptr<int> p7(new int[10], deleteInt);

    //也可以写成lamd 表达式

    std::shared_ptr<int> p7( new int[10], [](int* p) {delete[]p;} );

     某些特殊场景必须要自己自定义  delete 函数 传进shared_ptr 中去 如下:

    int a = 10;
    int *pb = &a;//普通指针,指向a对象
    std::shared_ptr<int> ptrb(&a);//默认使用delete 
    std::shared_ptr<int> ptrb(pb);//默认使用delete 
    
    int a = 10;
    int *pb = &a;//普通指针,指向a对象
    std::shared_ptr<int> ptrb(&a, [](int *x) {delete x; });//定义了lambda作为删除器
    std::shared_ptr<int> ptrb(pb,[](int *x) { delete x; });//定义了lambda作为删除器
    
    
    string *pia = new string[10];
    //delete[] pia;//正确,当 new 一个有析构函数的对象数组的时候 必须要用 delete[]删除
    //delete pia;//错误
    
    shared_ptr<string>sp(pia, [](string *p) {delete[] p; });//正确
    //shared_ptr<string>sp(pia);//错误
    //shared_ptr<string>sp(pia, [](string *p) {delete p; });//错误

     踩坑【错误1】试图从raw指针隐式转换到智能指针

    shared_ptr<Rect> p5 = new Rect(r_points, r_width, r_height); // !!!

     【错误2】将非动态分配的内存托管给智能指针

    Rect rect_6(r_points, r_width, r_height);
    shared_ptr<Rect> p6(&rect_6); // !!!  将栈 变量用初始化智能指针肯定不对哈
    

     【错误3】将同一份动态内存托管给多个智能指针

    Rect *xx = new Rect(r_points, r_width, r_height);
    shared_ptr<Rect> p7(xx);
    {
        shared_ptr<Rect> p8(xx); // !!!
        shared_ptr<Rect> p9(p7.get()); // !!!
    }
    xx = nullptr;
    Rect rect_7 = *p7;

    《Cpp Primer》中提到几条基本规范,建议严格遵循: 1.不使用相同的raw指针初始化(或reset)多个智能指针。 2.不delete get()返回的指针。 3.不使用get()初始化或reset另一个智能指针。 4.如果你使用get()返回的指针,记住当最后一个对应的智能指针销毁后,你的指针就变为无效了。 5.如果你使用智能指针管理的资源不是new分配的内存,记住传递给它一个删除器。

     3 智能指针初始化 要注意 应为 shared_ptr等智能指针 构造函数是 explicit 显示的构造函数不能用 指针隐式转换

    // 我们可以用new返回的指针来直接初始化智能指针:
    shared_ptr<int> p(new int(42));//p指向一个值为42的int对象
    
    //注意:接受指针参数的智能指针构造函数是explicit的,因此我们不能将一个内置指针隐式转换为一个智能指针,必须使用直接初始化形式!!!
    shared_ptr<int> p = new int(42));//错误,必须使用直接初始化
    //error C2440: “初始化”: 无法从“int *”转换为“std::shared_ptr<int>”,普通指针不能直接赋值给智能指针

     <深入应用c++11> 也有一些总结

     ====================================================================================================

    Effective Modern C++ 之 优先选用make_unique和make_shared  还没理解下次总结

    make_shared 使用:

    此函数再动态内存中分配一个对象,使用args初始化此对象,返回一个指向此对象的shared_ptr

    调用形式:make_shared<T>(args)

    这里的args可以是空字面值常量变量、 能与T类型的某个构造函数相匹配的参数列表等

    1)空
    //指向一个默认值初始化的int对象,此对象值为0
    shared_ptr<int> p0=make_shared<int>();
    2)字面值常量 
    //指向一个值为42的int
    shared_ptr<int> p1=make_shared<int>(42);
    3)变量
    //使用a初始化一个动态分配的类型为int的对象,注意这个对象和a不是同一个对象  注意:  这个对象和a不是同一个对象,这个对象是make_shared函数在动态内存中分配出来的一个对象,使用a进行值初始化,所以这个对象的值和a的值是相等的,但不是同一块内存!!!
    int a = 10;
    shared_ptr<int> p2=make_shared<int>(a);
    4)能与T类型的某个构造函数相匹配的参数列表
    //指向一个值为“9999999999”的string
    shared_ptr<int> p3=make_shared<string>(10,'9');
  • 相关阅读:
    ActiveMQ (一) 简介
    MSMQ .NET下的应用
    MSMQ
    RabbitMq C# .net 教程
    Rabbit MQ
    Dynamics 365—脚本
    DNS服务器地址汇总
    特殊字符 编码
    4s前置摄像头调用
    登陆前后导航栏处理 2015-12-12
  • 原文地址:https://www.cnblogs.com/zhangkele/p/15618794.html
Copyright © 2020-2023  润新知