(四)C++序列容器存储智能指针详解

通常用容器保存指针比保存对象更好,保存智能指针比原生指针好。

在容器中保存指针需要复制指针而不是它所指向的对象。复制指针通常比复制对象快。

在容器中保存指针可以得到多态性。存放元素基类指针的容器也可以保存其派生类型的指针。

对指针容器的内容进行排序的速度要比对对象排序快,因为只需要移动指针,不需要移动对象。

保存智能指针要比保存原生指针安全,因为在对象不再被引用时,自由存储区的对象会被自动删除。这样就不会产生内存泄漏。不指向任何对象的指针默认为nullptr.

主要有两种类型的智能指针:unique_ptr<T>和shared_ptr<T>,其中unique_ptr<T>独占它所指向对象的所有权,而shared_ptr<T>允许多个指针指向同一对象。

(1) 初始化

shared_ptr<string> p1;
if(!p1) cout<<”p1==NULL”<<endl;  //默认初始化的智能指针中保存着一个空指针
shared_ptr<string> p1(new string);   //empty时属于string的成员函数
shared_ptr<int> pa=new int(1);     //error:不允许以暴露裸露的指针进行赋值操作

//一般的初始化方式
shared_ptr<string> pint(new string(“normal usage!”));
cout<<*pint<<endl;

//推荐的安全的初始化方式
shared_ptr<string> pint1=make_shared<string>(“safe uage!”);
cout<<*pint1<<endl;

(2)get()函数

返回一个内置指针,指向智能指针的管理的对象。此函数设置的初衷是当我们向不能使用智能指针的代码传递一个内置指针。使用get返回指针的代码不能delete此指针。

shared_ptr<int> p1=make_shared<int>(32);
shared_ptr<int> p2(p1.get());  //错误的用法:但是p1、p2各自保留对一段内存的引用计数,其中有一个引用计数耗尽,资源也就释放了

(3)make_shared函数

最安全的分配和使用动态内存的方法是调用一个名为make_shared的标准库函数,此函数在动态内存中分配一个对象并初始化它,返回此对象的shared_ptr。

shared_ptr<int> p3=make_shared<int>(42);
shared_ptr<string> pstr=make_shared<string>(“99999”);
auto pau=make_shared<string>(“auto”);   //更简单,更常用的方式

使用make_shared用其参数来构造给定类型的对象;传递的参数必须能够与该类型的某个构造函数相匹配。

(4) shared_ptr的拷贝和赋值

当进行拷贝或者赋值操作时,每个shared_ptr都会记录有多少个其他的shared_ptr指向相同的对象

auto p=make_shared<int>(42);  //p指向的对象只有p一个引用者
cout<<p.use_count()<<endl;
auto q(p);                   //p和q指向相同的对象,此对象有两个引用者
cout<<p.use_count()<<endl;

(5) 引用计数

可以认为每个shared_ptr都有一个关联的计数器,通常称其为引用计数。无论何时我们拷贝一个shared_ptr,计数器都会递增。例如,当用一个shared_ptr去初始化另一个shared_ptr;当我们给shared_ptr赋予一个新的值或者是shared_ptr被销毁时,计数器就会递减。一旦一个shared_ptr的计数器变为0,就会自动释放自己所管理的对象

(6) 用erease节省内存

对于一块内存,shared_ptr类保证只要有任何shared_ptr对象引用它,他就不会被释放掉。由于这个特性,保证shared_ptr在不用之后不再保留就非常重要,通常这个过程能够自动执行而不需要人工干预,有一种例外就是我们将shared_ptr放在容器中。所以永远不要忘记erease不用的shared_ptr。

list<shared_ptr<string>> pstrList;
pstrList.push_back(make_shared<string>(“1111”));
pstrList.push_back(make_shared<string>(“222”));
pstrList.push_back(make_shared<string>(“333”));
pstrList.push_back(make_shared<string>(“4444”));
for(auto p:pstrList)
{
if(*p==”333”)
{
/*do something*/
}
cout<<*p<<endl;
}
//包含”333”的数据已经使用完
list<shared_ptr<string>>::iterator itr=pstrList.begin();
for(;itr!=pstrList.end();++iter)
{
if(**itr==”333”)
{
cout<<**itr<<endl;
pstrList.erase(itr);
}
}

 总结shared_ptr使用的基本规范:

不使用相同的内置指针值初始化(或reset)多个智能指针

不delete get函数返回的指针

如果你使用get返回的指针,记住当最后一个对应的智能指针销毁后,你的指针就变为无效了

如果你使用智能指针管理的资源不是new分配的内存,记得传递给他一个删除器。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本版本与网上其他资源不同之处在于,此版本可进行编辑,搜索,已进行内容识别扫描。可全选,可编辑,可剪切文字。 部分目录如下: 目录 第一篇预备知识 第1 章C++ 编程技术...................................................... 3 1-1 C++与C 语言的区别................................................... 4 1-1-1 文件扩展名的改变,.............................................. 4 1-1-2 简化输入/输出手段.............................................. 5 1-1-3 数据类型声明的改变,............................................ 5 1-1-4 动态内存分配运算符的使用....................................... 6 1-1-5 弓I 用(References) 类型, ··················•················•"'''8 1-1-6 const 语义的扩展................................................ 9 1-1-7 指针声明类型与对象类型相一致.................................. 13 1-1-8 int 与char 不再等价............................................. 13 1-1-9 结构数据类型的变化............................................ 13 1-1-10 数组和指针技术的不同......................................... 14 1-2 C++存储技术........................................................ 15 1-2 一I C++存储类型.................................................. 15 I6I7 ..... .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. •. .• •. .• .. .. .. .. .. .. .. .. .. .. .. .. . 期 符存 饰生 修的 取象 存对 廿廿 I2I32 ~3 c c 1-3 C++ 函数技术........................................................ 19 1-3-1 类的构造函数、析构函数与赋值函数,..... - ........ - .............. 19 1-3-2 在派生类中实现类的基本函数,................... _ ............... 29 1-3-3 内联函数技术,........ ................................... 30 3133 ..... .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. . 现 实 术的 技制 数机 函象 元对 友向 由 曰1. l -C 1 4 3337 ..... .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. . 术术 技技 承载 继重 的数 类函 l4l44 3 ~ 3840 ..... .. .. .. .. .. .. •. .• .. .. .. .. .. .. .. .. .. .. .. •. .• .. •. .• •. •• .• .. .. .. .. .. .. .. .. .. •. •• .• . 术 技 类 术象 技抽 载和 重数 符函 算虚 运纯 l4l34 4 1-5 小结...............................................
本书是一本优秀的C++教材,内容包括:基础类型、操作符和简单变量,循环和决策,命名空间和C++标准库,用C++编写函数,行为、序列点和求值顺序,泛型函数,用户自定义类型、指针、智能指针、迭代器和动态实例,动态对象创建和多态对象,流、文件和持久性,异常,重载操作符和转换操作符,容器、迭代器和算法等。作者重点介绍类、模板、操作符重载、异常、命名空间等从事现代C++编程不可或缺的语言特性,以及容器、算法、迭代器等重要的标准库组件。本书通过例子代码和“代码详解”,将C++的精华展示给读者。.<br>本书可供完全不同的读者群体使用。无论你是否有编程基础,都可以从本书中受益。<br>学习C++的过程可能很枯燥。为了使学习过程生动有趣,Francis Glassborow以其独树一帜的激励风格讲解编程任务和工具,使你得以迅速开始编程。他的教学方式鼓舞人心,并提供了亲手打造的例子和项目。图形用户界面(GUI)扩展可为你提供即时反馈,你可从创建GUI程序中获得更多的乐趣。每一章末尾的参考素材则为你提供进一步的帮助。..<br>本书带有一款完全可移植的开源编译器,以及针对Windows和Linux的IDE。书中广泛地使用了作者的图形库,为你带来丰富的辅助素材,以便迅速有效地处理编程任务。<br>如果你已经通过自学掌握了编程基础,或在工作中学会了基本的编程技能,那么本书非读不可!它将把你的编程水平推向更高的层次。在学习过程中你一定会获得许多乐趣!...

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值