条目八《永不建立auto_ptr的容器》

重要的事说三次,永不建立auto_ptr的容器,永不建立auto_ptr的容器,永不建立auto_ptr的容器!!!

为什么?

实质是auto_ptr指针在转移时把原本的指针置为NULL,然而在STL容器中的一些操作是包含数据转移操作的。

比如排序sort(),在STL中,容器的sort的底层是基于多种排序算法的,其中的快排更是最重要的一种。快排的核心是每次递归选出一个基准值,然后把数据分为大小于基准值两部分,直至整个数据排列完成。

假如是auto_ptr容器,在每次递归的时候,基准值会转移为NULL,并且这个基准值局部变量在当前递归结束时会被销毁,因此会发生整个快排下来,整个数据会有几个数值是缺少的和为NULL的,这些数据都是每次递归选出来的基准值。

请看stl源码:

bool widgetAPCompare(const auto_ptr<Widget>& lhs, const auto_ptr<Widget>& rhs)
{
return *lhs < *rhs;
}
vector<auto_ptr<Widget> > widgets;
sort(widgets.begin(), widgets.end(), widgetAPCompare);

这是一个vector的sort例子。

template<class RandomAccessIterator, class Compare>
void sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp)
{
typedef typename iterator_traits<RandomAccessIterator>::value_type ElementType; //先忽略此句,这里主要是获取数据的类型
RandomAccessIterator i; //i指向基准值
...
ElementType pivotValue(*i); //把基准值复制到局部临时变量中
...
}

这里的重点的这一句ElementType pivotValue(*i);,解释直接参考书的:

它把一个元素从保存的区间拷贝到局部临时对象中。在我们的例子里,这个元素是一个auto_ptr,所以这个拷贝操作默默地把被拷贝的auto_ptr——vector中的那个——设为NULL。另外,当pivotValue出了生存期,它会自动删除指向的Widget。这时sort调用返回了,vector的内容已经改变了,而且至少一个Widget已经被删除了。

其实这个很容易理解,就是因为是auto_ptr容器,如果调用容器的操作涉及到容器元素转移的会造成把容器原数据的置为NULL,并且元素会被删除,删除个数是递归的个数。

条目八《永不建立auto_ptr的容器》的更多相关文章

  1. 切勿创建包括auto_ptr的容器对象

     当你拷贝一个auto_ptr时,它所指向的对象的全部权被移交到拷入的auto_ptr上,而它自身被置为NULL.我的理解是:拷贝一个auto_ptr意味着改变它的值.比如: auto_ptr&l ...

  2. STL学习系列八:Set和multiset容器

    1.set/multiset的简介 set是一个集合容器,其中所包含的元素是唯一的,集合中的元素按一定的顺序排列.元素插入过程是按排序规则插入,所以不能指定插入位置. set采用红黑树变体的数据结构实 ...

  3. .Net Core微服务入门全纪录(八)——Docker Compose与容器网络

    Tips:本篇已加入系列文章阅读目录,可点击查看更多相关文章. 前言 上一篇[.Net Core微服务入门全纪录(七)--IdentityServer4-授权认证]中使用IdentityServer4 ...

  4. stl学习记录(1)

    Effective STL 中文版学习记录 条款4 判断容器是否为空 使用empty而不是size().size()操作在实现上不是一个时间常数操作条款5 尽量使用区间成员函数代替它们的单元素兄弟.S ...

  5. c++继承构造子类调用父类构造函数的问题及关于容器指针的问题及当容器里储存指针时,记得要手动释放

    看下面的一个问题: class Person { private: string name; public: Person(const string& s=""){ nam ...

  6. docker容器修改时区(java应用log信息与标准容器时间有八个小时时间差)

    在docker容器中运行的java应用打出的日志时间和通过date -R方式获取的容器标准时间有八个小时时间差- 因为docker容器的原生时区为0时区,为了和国内时区保持一致,需要把容器时区调为东八 ...

  7. 在docker for windows建立mssql容器后,ssms连接mssql出现错误号码18456的问题

    在docker for windows建立mssql容器后,ssms连接mssql出现错误号码18456的问题 笔者提供一个可能会没考虑到的点. 请检查本机是否安装了mssql!!! 请检查本机的ms ...

  8. C++ 顺序容器

    <C++ Primer 4th>读书笔记 顺序容器内的元素按其位置存储和访问.容器类共享公共的接口,每种容器类型提供一组不同的时间和功能折衷方案.通常不需要修改代码,只需改变类型声明,用一 ...

  9. C++ Primer 学习笔记_38_STL实践与分析(12)--集成的应用程序容器:文本查询程序

    STL实践与分析 --容器的综合应用:文本查询程序 引言: 本章中最重点的实例.由于不须要用到multiset与multimap的内容.于是将这一小节提到了前面.通过这个实例程序,大师分析问题的智慧, ...

随机推荐

  1. scala 在vim中的语法高亮

    https://github.com/derekwyatt/vim-scala 提供了一个选择 看install手册,发现两个命令都是必须的. mkdir -p ~/.vim/{ftdetect,in ...

  2. smack 监听不同packet机制

    之前做即时通讯,扒了smack源码来参考.说下其中解包后进行通知的机制. Filter类:accept(Packet packet)函数,传入packet在此函数中进行对比判断,返回true 则通过此 ...

  3. Subscript & Inheritance

    [Subscript] 1.subscript的定义: 2.Subscript的使用: 3.可以定义多维subscript: 多维Subscript的使用: [Inheritance] 1.overr ...

  4. 玩转Mysql命令

    连接数据库mysql -hlocalhost -uroot -p 在MYsql的跟目录文件下进行 show databses:展示所有数据库 解决方法1:在MySql安装目录下找到my.ini,将[m ...

  5. Linux3基本命令 ls,pwd,cat,echo,mv,cp,mkdir,rm,ln

    ls 列出文件名称. -l 列出长文件名称. -rwxr-xr-- 1 root root 10739 Dec 23 13:31 bbscon (7)          (4) (5) (6)     ...

  6. Java 基于quartz实现定时 之一(注解方式配置)

    需要在项目里,导入quartz.jar package cn.zr.pringmvctest.trigger; import org.springframework.context.annotatio ...

  7. SqlServer------范式小结

    说明:大多数初学者对于关系数据库中的范式很是头疼,我本人也是,所以今天又看了视频,总结了一下内容,尽量语言通俗易懂,少用专业术语以及概念. 首先要理解几个键值. 超键:在关系模式中,能唯一标识元组的属 ...

  8. 1.介绍templates

    我们现在要计算int和double类型数据的平方,我们就需要2个函数: #include <iostream> using namespace std; int square(int x) ...

  9. 专题2-通过按键玩中断\第1课-中断处理流程深度剖析-lesson1

    中断概念 1.中断生命周期 串口先产生一个事件,该事件传送到中断控制器里面,中断控制器会进行相应过滤,能通过过滤,那么就交给CPU去处理. 2.中断源 2440芯片手册 6410芯片手册 3.中断过滤 ...

  10. maven构建非法字符解决办法

    CI使用maven做版本构建时候碰到了一个问题,有个java源码始终编译报错,错误发生在文件第一行. 出错内容是: ***.java:[1,1] 非法字符: \65279 后面上网看了,原来是文件编码 ...