首页 > 编程语言 >c++ primer plus 第16章string 类和标准模板库,16.2.1 使用智能指针

c++ primer plus 第16章string 类和标准模板库,16.2.1 使用智能指针

时间:2024-07-18 19:55:23浏览次数:17  
标签:string 16 auto c++ 使用 new unique ptr

c++ primer plus 第16章string 类和标准模板库,16.2.1 使用智能指针

c++ primer plus 第16章string 类和标准模板库,16.2.1 使用智能指针

文章目录


16.2.3 unique ptr为何优于 auto ptr

请看下面的语句:

auto ptr<string>pl(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<string>demo(const char*s)
{
    unique ptr<string>temp(new string(s));
    return temp;
}

并假设编写了如下代码:

unique ptr<string> ps;
ps = demo("Uniquely special");

demo( )返回一个临时 unique pt,然后 ps 接管了原本归返回的 unique ptr 所有的对象,而返回的unique pt 被销毁。这没有问题,因为 ps拥有了 string对象的所有权。但这里的另一个好处是,demo()返回的临时 unique_ptr 很快被销毁,没有机会使用它来访问无效的数据。换句话说,没有理由禁止这种赋值。神奇的是,编译器确实允许这种赋值!
总之,程序试图将一个 unique ptr 赋给另一个时,如果源 unique ptr 是个临时右值,编译器允许这样做;如果源uniqueptr将存在一段时间,编译器将禁止这样做:

using namespace std;
unique_ptr< string>pul(new string "Hi ho!");
unique_ptr< string> pu2;
pu2 = pul;//#1 not allowed
unique_ptr<string> pu3;
pu3 =unique_ptr<string>(new string "Yo!");//#2 allowed

语句#1将留下悬挂的 unique ptr(pul),这可能导致危害。语句#2不会留下悬挂的unique ptr,因为它调用 unique ptr 的构造函数,该构造函数创建的临时对象在其所有权转让给 pu后就会被销毁。这种随情况而异的行为表明,unique ptr优于允许两种赋值的 auto ptr。这也是禁止(只是一种建议,编译器并不禁止)在容器对象中使用 auto ptr,但允许使用 unique ptr 的原因。如果容器算法试图对包含 unique ptr 的容器执行类似于语句#1的操作,将导致编译错误;如果算法试图执行类似于语句#2的操作,则不会有任何问题。
而对于 auto ptr,类似于语句#1的操作可能导致不确定的行为和神秘的崩溃。当然,您可能确实想执行类似于语句#1的操作。仅当以非智能的方式使用遗弃的智能指针(如解除弓用时),这种赋值才不安全。要安全地重用这种指针,可给它赋新值。C++有一个标准库函数 std:move(),让您能够将一个 unique ptr赋给另一个。下面是一个使用前述demo()函数的例子,该函数返回一个unique ptr对象:

using namespace std;
unique_ptr<string>psl,ps2;
psl =demo("Uniquely special");
ps2 =move(psl);//enable assignment
ps1 = demo(" and more");
cout<<*ps2<<*psl << endl;

您可能会问,uniqueptr如何能够区分安全和不安全的用法呢?答案是它使用了C++11新增的移动构造函数和右值引用,这将在第18章讨论。
相比于 auto ptr,unique_ptr 还有另一个优点。它有一个可用于数组的变体。别忘了,必须将 delete 和new 配对,将 delete П和 new []配对。模板 auto ptr 使用 delete 而不是 delete[],因此只能与 new 一起使用,而不能与 new[]一起使用。但 unique ptr 有使用 new[]和 delete []的版本:

std::unique ptr< double[]>pda(new double(5));// will use delete []

警告:使用new分配内存时,才能使用auto ptr和shared ptr,使用 new[]分配内存时,不能使用它们。不使用 new分配内存时,不能使用 auto ptr或shared ptr;不使用 new或new[分配内存时,不能使用unique ptro

标签:string,16,auto,c++,使用,new,unique,ptr
From: https://blog.csdn.net/zhyjhacker/article/details/140531277

相关文章

  • c++ primer plus 第16章string 类和标准模板库,16.2.2 有关智能指针的注意事项
    c++primerplus第16章string类和标准模板库,16.2.2有关智能指针的注意事项c++primerplus第16章string类和标准模板库,16.2.2有关智能指针的注意事项文章目录c++primerplus第16章string类和标准模板库,16.2.2有关智能指针的注意事项16.2.2有关智能指针的......
  • C++ 面向对象程序设计 ---- 类2重点
    1.构造函数,代替Init()函数构造函数的特点1.函数名与类名相同2.无返回值,void也不需要写3.对象实例化时,系统会自动调用构造函数4.构造函数可以重载classDate{public://函数名与类名相同,无返回值Date()//函数重载,无参{_year=1;......
  • 什么是信息指纹和信息加密——《数学之美》第16、17章以及其他各种资料的读书笔记
    目录1.信息指纹1.1概念1.2相关算法的演进历程1.3 哈希碰撞1.4 雪崩效应1.5 应用场景2.信息加密2.1密码学的简要历史2.1.1古代密码学:智慧的萌芽2.1.2 中世纪至文艺复兴:密码术的兴起2.1.3 近代密码学:机械密码机的诞生2.1.4 现代密码学:复杂科学的诞生2.......
  • 16 触发器
    概念触发器trigger是一种特殊类型的存储过程。触发器主要是通过事件进行触发而被执行,而存储过程是可以直接通过存储过程的名字被调用执行触发器的作用1、可以在写入数据表前,强制检验或转换数据,以保证数据安全2、触发器发生错误时,异动的结果会被撤销如果触发器执行发生错误......
  • OI学习笔记(C++)
    笔记完整版链接参照oi.wiki整理了基础dp的一些笔记:学习笔记+模板(Adorable_hly)(自己结合网络和做题经验总结的,dalao勿喷)第一大板块:DP动态规划适用场景:1.最优化原理:若该问题所包含的子问题解是最优的,就称该问题具有最优子结构,满足最优化原理。2.无后效性:指某一阶段的状......
  • Error: Expected ref to be a function, a string, an object returned by React.crea
    1、完整报错:Error:Expectedreftobeafunction,astring,anobjectreturnedbyReact.createRef(),ornull.atcoerceRef(react-dom.development.js:14873:1)atreconcileSingleElement(react-dom.development.js:15723:1)atreconcileChildFibers(re......
  • C++异常
    异常描述std::exception该异常是所有标准C++异常的父类。std::bad_alloc该异常可以通过new抛出。std::bad_cast该异常可以通过dynamic_cast抛出。std::bad_typeid该异常可以通过typeid抛出。std::bad_exception这在处理C++程序中无法预期的异......
  • C++文件和流
    要在C++中进行文件处理,必须在C++源代码文件中包含头文件<iostream>和<fstream>。数据类型描述fstream该数据类型通常表示文件流,且同时具有ofstream和ifstream两种功能,这意味着它可以创建文件,向文件写入信息,从文件读取信息。ofstream该数据类型表示输出......
  • C++中的vector对应Java中的什么类型?
    C++中的vector对应Java中的ArrayList类型。‌C++中的vector和Java中的ArrayList都是可变长的数组或数组列表,‌它们具有以下相似特性:‌两者都是动态数组,‌可以根据需要自动增长。‌它们都支持通过索引访问元素,‌并且元素是有序的。‌它们都提供了添加、‌删除和查询元素的方法......
  • 7.16 网络流
    网络流和费用流,其实知道如何建图之后就可以直接套板子了,但正如konata所言,这些题如果不是在今天作业里,打死也想不到要用网络流。善意的投票这个是最小割的典型问题,把睡午觉视为集合a,即原点,不睡视为集合b,即汇点,那么对每个点,连向自己意愿的容量为1,违背的容量为0。对于一对朋友,他们......