zoukankan      html  css  js  c++  java
  • 【校招面试 之 C/C++】第27题 C++ 智能指针(三)之 unique_ptr

    auto_ptr<string> p1(new string ("auto") ; //#1
    auto_ptr<string> p2;                       //#2
    p2 = p1;                                   //#3
    

    在语句#3中,p2接管string对象的所有权后,p1的所有权将被剥夺。前面说过,这是好事,可防止p1和p2的析构函数试图刪同—个对象;

    但如果程序随后试图使用p1,这将是件坏事,因为p1不再指向有效的数据。

    下面来看使用unique_ptr的情况:

    unique_ptr<string> p3 (new string ("auto");   //#4
    unique_ptr<string> p4;                       //#5
    p4 = p3;                         //#6

    编译器认为语句#6非法,避免了p3不再指向有效数据的问题。因此,unique_ptr比auto_ptr更安全。

    但unique_ptr还有更聪明的地方。
    有时候,会将一个智能指针赋给另一个并不会留下危险的悬挂指针。假设有如下函数定义:

    unique_ptr<string> demo(const char * s)
    {
        unique_ptr<string> temp (new string (s)); 
        return temp;
    }
    

    并假设编写了如下代码:

    unique_ptr<string> ps;
    ps = demo('Uniquely special");
    

    demo()返回一个临时unique_ptr,然后ps接管了原本归返回的unique_ptr所有的对象,而返回时临时的 unique_ptr 被销毁,也就是说没有机会使用 unique_ptr 来访问无效的数据,换句话来说,这种赋值是不会出现任何问题的,即没有理由禁止这种赋值。实际上,编译器确实允许这种赋值,这正是unique_ptr更聪明的地方。

    总之,当程序试图将一个 unique_ptr 赋值给另一个时,如果源 unique_ptr 是个临时右值,编译器允许这么做;如果源 unique_ptr 将存在一段时间,编译器将禁止这么做,比如:

    unique_ptr<string> pu1(new string ("hello world"));
    unique_ptr<string> pu2;
    pu2 = pu1;                                      // #1 not allowed
    unique_ptr<string> pu3;
    pu3 = unique_ptr<string>(new string ("You"));   // #2 allowed

    #1留下悬挂的unique_ptr(pu1),这可能导致危害。而#2不会留下悬挂的unique_ptr,因为它调用 unique_ptr 的构造函数,该构造函数创建的临时对象在其所有权让给 pu3 后就会被销毁。这种随情况而已的行为表明,unique_ptr 优于允许两种赋值的auto_ptr 。

    当然,您可能确实想执行类似于#1的操作,仅当以非智能的方式使用摒弃的智能指针时(如解除引用时),这种赋值才不安全。要安全的重用这种指针,可给它赋新值。C++有一个标准库函数std::move(),让你能够将一个unique_ptr赋给另一个。下面是一个使用前述demo()函数的例子,该函数返回一个unique_ptr<string>对象:
    使用move后,原来的指针仍转让所有权变成空指针,可以对其重新赋值。

    unique_ptr<string> ps1, ps2;
    ps1 = demo("hello");
    ps2 = move(ps1);
    ps1 = demo("alexia");
    cout << *ps2 << *ps1 << endl;
    

      

  • 相关阅读:
    达梦数据库学习(二、管理数据库实例)
    达梦数据库学习(一、linux操作系统安装及数据库安装)
    SQL Server 数据库还原进度查看
    关于索引的学习(主要是聚集索引与非聚集索引)
    SQL Server批量向表中插入多行数据语句
    最大流-前置push-relabel算法实现
    调度算法(二)
    调度算法(一)
    软件工程:提问回顾
    软件工程:个人阅读作业与总结
  • 原文地址:https://www.cnblogs.com/xuelisheng/p/9350765.html
Copyright © 2011-2022 走看看