条目八《永不建立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. 常用的正则规则,直接copy就OK了

    import  re #用户名验证:(数字字母或下划线6到20位)re.match("/^\w{6,20}$/",匹配对象) #邮箱验证: re.match(" /^[a ...

  2. Windchill 设计变更流程卡死查询方法

    设计变更流程卡死查询方法 1. 导出设计变更表单查看填写了“需要”和“是”字眼的文本框  2.打开进程管理器显示流程卡死的地方,确定哪里出错导致没法执行下一步  3.打开设计变更流程图,里面可以查看有 ...

  3. error:crosses initialization of ...的解决办法

    switch(c) { case 0x01: int temp = a + b; .... break; case 0x02: break; default:break; } 此时会报如题所示错误 原 ...

  4. JAVA环境安装配置

    dk1.6 64位是 Java 语言的软件开发工具包,主要用于移动设备.嵌入式设备上的java应用程序. jdk1.6 64位安装教程 jdk1.6 64位JDK的安装路径:D:\Program Fi ...

  5. sqLSERVER 计划缓存

    在这一期的性能调优培训里,我想详细谈下SQL Server里计划缓存及其副作用.在上一周你已经学到,每个提交给SQL Server的逻辑查询会编译成物理执行计划.那个执行计划然后会被缓存,即被称为计划 ...

  6. 面试题:volatile关键字的作用、原理

    在只有双重检查锁,没有volatile的懒加载单例模式中,由于指令重排序的问题,我确实不会拿到两个不同的单例了,但我会拿到“半个”单例. 而发挥神奇作用的volatile,可以当之无愧的被称为Java ...

  7. 用CSS3.0画圆

    CSS3.0中有一个border-radius属性,这个属性允许向 div 元素添加圆角边框,也就是div边角不再一直是直角,在CSS3.0中可以做成圆角了,所以我们可以用这个属性用div画一个圆,或 ...

  8. Part3_lesson3---ARM伪指令学习

    1.ARM机器码 对elf格式的文件进行反汇编可得到相应汇编文件的机器码: arm-linux-objdump -D -S start.elf 机器码的解析,可以参考文件ARM Architectur ...

  9. Entity Framework 6.0 Tutorials(2):Async query and Save

    Async query and Save: You can take advantage of asynchronous execution of .Net 4.5 with Entity Frame ...

  10. ByteUnit

    JDK里面有TimeUnit,看spark源码有个ByteUnit.这个类还是挺不错的. public enum ByteUnit { BYTE (1), KiB (1024L), MiB ((lon ...