zoukankan      html  css  js  c++  java
  • C++ 智能指针auto_ptr、shared_ptr、unique_ptr《二》-----为何unique_ptr优于auto_ptr

    1、auto_ptr

    例如:

    auto_ptr<string> p1(new string("auto"));
    auto_ptr<string> p2;
    p2 = p1;

    执行后的局部变量:

    上述代码执行到第三行之后,p2接管string对象的所有权,p1的所有权被剥夺。虽然,可防止p1和p2的

    析构函数试图删除同一个对象;但是,程序如果试图删除p1,这是矛盾的,因为p1不再指向有效数据

    2、unique_ptr

    例如:

    unique_ptr<string> p3(new string("auto"));
    unique_ptr<string> p4;
    p4 = p3;

    程序第三行提示错误,如果编译,则显示错误信息:尝试引用已删除的函数

    编译器认为第三行非法,避免了p3不再指向有效数据的风险,因此unique_ptr 比 auto_ptr 更安全

    编译阶段的错误比潜在的程序崩溃更安全

    3、有时候,将一个智能指针赋值给另一个并不会留下 一个具有风险的悬挂指针

    #include<memory>
    #include<iostream>
    
    using namespace std;
    
    unique_ptr<string> demo(const char* s)
    {
        unique_ptr<string> temp(new string(s));
        return temp;
    }
    
    int main()
    {
        unique_ptr<string> ps;
        ps = demo("uniquely special");
    
        return 1;
    }

    demo() 返回一个临时的 unique_ptr , 然后ps接管了原本 函数返回的 unique_ptr指向的对象,而返回的unique_ptr被销毁。这都没问题,因为ps拥有了string对象的所有权。这里一个好处是demo()返回的临时unique_ptr很快被销毁,没有机会使用它来访问无效的数据。上述做法是编译器允许的程序试图将一个unique_ptr赋给另一个时候,如果源unique_ptr是个临时右值,编译器允许这样做;如果源unique_ptr将存在一段时间,编译器将会禁止这样做再看以下情况:

    1 using namespace std;
    2 unique_ptr<string> pu1(new string ("hi !"));
    3 unique_ptr<string> pu2;
    4 pu2 = pu1;//pu1将会存在下去,抱持悬空
    5 unique_ptr<string> pu3;
    6 pu3 = unique_ptr<string>(new string ("Yo"));//临时右值

    这段代码编译不能通过。上述第4行将留下悬挂的 unique_ptr(pu1),将会有风险,pu2接管这个string;第6行则不会,因为调用unique_ptr的构造函数,该构造函数创建的临时对象将其所有权装让给pu3之后,将会被销毁。

    小结:所以实际应用过程中,你最好不要用auto_ptr

    4、c++标准库函数std::move()

            在容器对象中,禁止使用auto_ptr,允许使用unique_ptr。

            对于unique_ptr而言,容器算法试图对包含unique_ptr的容器执行 类似于上述第4行的操作,这将导致编译错误【要想做这种操作,解决方案是使用 move函数,请看下文】;

    执行 类似于上述第6行的操作,这将OK。

            对于auto_ptr而言,容器算法试图对包含auto_ptr的容器执行 类似于上述第4行的操作,将导致不确定行为和神秘崩溃。如果,你试图对包含unique_ptr的容器执行 类似于上述第4行的操作,我们将上述代码改为:

    using namespace std;
    unique_ptr<string> pu1(new string ("hi !"));
    unique_ptr<string> pu2;
    //pu2 = pu1;//编译不能通过
    pu2 = move(pu1);//pu1将会存在下去,抱持悬空
     unique_ptr<string> pu3; pu3 = unique_ptr<string>(new string ("Yo"));//临时右值

    总结:

           使用 auto_ptr 指向对象,如果不慎错误使用,导致指针悬空,你很难发现,这种灾难会在代码运行阶段表现出来,可能你还不知道是这个原因导致;使用 unique_ptr指向对象,如果不慎错误使用,导致指针悬空,程序编译将不能通过,你将会发现对象指针悬空问题并及时作出更正。初此之外,我暂时觉得二者没什么卵区别。

           对于unique_ptr的安全使用问题,我强烈建议你去查看《c++ primer plus》第18章节 ,后续补充博客。

  • 相关阅读:
    微信公众平台二次开发需要配置的几个地址与参数
    Extjs4.1+desktop+SSH2 定义程序入口
    Extjs4.1+desktop+SSH2 搭建环境 项目能跑起来
    Liunx开发(Extjs4.1+desktop+SSH2超强视频教程实践)(2)
    Liunx开发(Extjs4.1+desktop+SSH2超强视频教程实践)(1)
    增量补丁打包器(我也不是想这么干的)
    部署git服务器(Windows Server 2008)
    测试发布(maven-assembly-plugin看好你哦)
    工作流性能优化(敢问activiti有扩展性?)(3)
    工作流性能优化(敢问activiti有扩展性?)(2)
  • 原文地址:https://www.cnblogs.com/winslam/p/9073205.html
Copyright © 2011-2022 走看看