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