容器使用的12条军规——《Effective+STL中文版》试读

    还 记的自己早年在学校学习c++的时候,老师根本就没有讲STL,导致了自己后来跟人说 起会C++的时候总是被鄙视,后来就下定决心一定要搞定STL。但是说实话,后来学了STL之后,我还是没有能够把它运用好,有的时候觉得STL太好了, 太强大了,大大减少了我编程的难度,但是另一方面,STL又有些复杂,自己还不能够确定哪里会产生错误以及错误的原因,这些陷进导致自己运用的时候总是蹑 手蹑脚,只用到了STL比较基础的一些功能(用容器放一些数据,用到一点儿基础的如find,sort之类的算法),不能充分发挥STL的 能力,不能运用自如。 这就好比金毛狮王费了很大劲抢得了屠龙刀,但是他却不懂怎么发挥屠龙刀的真正威力。本书的试读,仿佛让我看到了一线希望,因为本书的体例是以一种类似于条 款的方式来指导STL应用实践的,作者给我们揭示的是实实在在地在STL应用方面的专家级经验技巧和to do or not to do的规则。 (应该与不应该)

第一章阅读笔记

1.容器使用关注点


基本上书中所有写到的内容都是从这些方面出发来分析,我们在遇到非书中提到的情况时,可以基于以上这些关注点来具体展开分析。

2.基础知识点说明

(1)(STL提供的)容器有: 序列容器:标准(vector、string、deque、list)和非标准(slist、rope);
  关联容器:标准(set、multiset、map、multimap)和非标准(hash_set、hash_map、hash_multiset、hash_multimap)
  就存储方式而言,其中vector、string、deque、rope是连续内存的,其余表示链表的(list、slist)和关联容器是基于节点的。
 (2)标准非STL容器:数组、bitset、valarray、stack、queue、priority_queue
 (3)STL提供的迭代器按所支持的操作分类:输入迭代器、输出迭代器、前向迭代器、双向迭代器、随机访问迭代器
 (4)STL提供计算复杂性保证,用n表示元素个数,所提供操作的快慢程度:n足够大时,线性>对数>常数(>表示快于);相对较小的n时,理论上复杂的操作比理论上简单的操作性能好。
 (5)容器中数据布局和C兼容的只有vector;string和rope是基于引用计数的;只有list对多元素的插入提供事务语义;只有string在swap过程中会导致迭代器、指针和引用变为无效;deque是唯一的迭代器可能无效而指针和引用不会变为无效的标准容器。

3.实际经验使用条款

(1)不要编写独立于容器的代码,虽然泛型很好,但是还达不到这样的抽象程度。因为如果要编写独立于容器的代码,那么必然只能实现所有容器所提供的功能的交集,而这个交集的功能很少,这样做没有意义。
   但是可以对容器提供封装,用typedef或类来实现,使改变容器类型(更换容器)的操作变得容易。
 (2)不符合标准的代码,通过了编译将更危险。
 (4)避免使用vector<bool>,因为这时vector里面没有真正的存放bool对象。
 (3)STL的工作方式是基于拷贝的。这种方式通过拷贝构造函数和拷贝赋值操作符来实习。因此,向基类对象的容器中插入派生类对象几乎总是错误的,这回导致派生类对象的特化特性被“剥离”,避免这种现象而利用多态性的选择是智能指针。
 (4)检查容器为空时用empty()而不是size()==0,因为empty总是线性时间的,size()对于list而言则需要有所取舍,所以可能不同的STL平台实现不同,有的会是线性时间,有的会是常数时间。
 (5)使用时区间成员函数优先于对应的单元素成员函数。此时进行比较的关注点有:编码风格(代码长度(减少敲击)、表达意思的清晰度)和效率(调用内存分配子分配内存的次数、拷贝对象(对象移动)频繁程度、冗余操作、函数调用次数)。支持区间的成员函数:
 ①区间创建:container::container(InputIteratorbegin,InputIteratorend);  适用范围:所有标准容器
 ②区间插入:void container::insert(iteratorposition,InputIteratorbegin,InputIteratorend); 适用范围:所有标准序列容器
                    void container::insert(InputIterator begin,InputIteratorend);  适用范围:所有标准关联容器
 ③区间删除:iteratorcontainer::erase(iteratorbegin,iteratorend);适用范围:所有标准序列容器
                    voidcontainer::erase(iteratorbegin,iteratorend);   适用范围:所有标准关联容器
 ④区间赋值:void container::assign(InputIteratorbegin,InputIteratorend); 适用范围:所有标准容器
  功能弱一些的:operator=用于把一个容器拷贝到相同类型的另一个容器   适用范围:所有标准容器
 (6)由于函数类型的存在,所以要小心语法分析可能带来的问题。如:

list<int>data(istream_iterator<int>(dataFile), istream_iterator<int>());

这个定义可能会被编译器理解为一个data函数的声明,正确的做法是:

list<int> data(( istream_iterator<int>(dataFile))istream_iterator<int>());

但并不是所有编译器都支持,所以为了对所有编译器都没有二义性,更好的方式是在对data 的声明中避免使用匿名的istream_iterator 对象,如下:

1. ifstream dataFile("ints.dat");

2. istream_iterator<int> dataBegin(dataFile);

3. istream_iterator<int> dataEnd;

4. list<int> data(dataBegin,dataEnd);

(7)容器不是万能的,不能知道程序员真正做了什么,所以,如果容器中包含了通过 new操作创建的指针,切记在容器对象析构前将指针delete掉。可以通过创建函数对象来完成这项工作(两种不同模板化程度的实现提供不同的特性),但是不能够做到异常安全,所以建议采用的是智能指针。
(8)介于auto_ptr“复制一个auto_ptr意味着改变它的值”的特殊特性,避免创建包含auto_ptr的容器对象,auto_ptr不是智能指针!
(9)删除元素的方法,其中要考虑到迭代器实现啊:

(10)为了满足标准同一类型的分配子是等价的的条件,分配子(allocator)对象不可以有状态,这意味着可移植的分配子不可以有任何非静态的数据成员,至少不能有会影响其行为的数据成员;如果要编写分配子并且将它们同标准容器一起使用,分配子必须提供rebind模板,因为标准容器假定它是存在的;编写分配子时,传给分配子的allocate 成员函数的是那些要求内存的对象的个数,并不是类似于编写operator new 那样的字节数。简单的说,分配子的作用就是帮助我们自己定义内存管理的策略。
(11)在编程时,只能期望STL提供的操作具有线程安全性而不能依赖。所以,如果想要实现线程安全,可以自己动手通过获得互斥量(getMutexFor)和释放互斥量(releaseMutexFor)的方法来实现。考虑到防止忘记调用releaseMutexFor的可能性,好的解决方案是使用一个lock类来封装,构造函数获得互斥量,析构函数释放互斥量,只要在需要互斥访问同步的地方定义一个lock对象就可以了。

试读感受

整个第一章读下来,其实不是那么顺利,需要投入时间来“啃”。虽然作者所讲的内容都是实际的经验和技术,但是作者讲解的是非常深入的,所以正如作者书中提示的那样,需要停下来,瞪大眼睛看,仔细思考才能够真正理解背后的原理,只有这样也许在未来的应用中才能运用的得心应手。这本书的写作风格非常严谨,比如作者在引言中所说的书中所要用到的不是通用概念的STL平台,一些特殊样式所表达的意思,一些STL相关的书中出现的表达方式都给出说明,单从这方面而言就已经是专家级水准了。从内容而言,这本书所讲绝不仅仅是告诉读者怎么做,作者还会向我们一步步阐明这样做背后的原因,从多个角度去分析各种实现手段的优劣,步步深入地从简单的能够达到任务的方法到最好的方案向我们展示整个分析过程和分析方法,这一整套的思维体系和框架值得每个程序设计人员去学习和应用。本书的体例是条款式的,这样的好处就是虽然本书有些地方讲解的比较深奥,但是各个条款的内容又不是太多,所以可以让读者无形中增加读下去的信心而不轻易放弃!总之,这是一本精心编排的重量级的经验技巧书籍,每一个希望用好STL的人都应该人手必备,每个程序员都该学习其中的思考方法。当然,我也希望能够通篇的研读!

——L0mio


【美】梅耶 (Meyers,S.)  著

潘爱民  陈铭  邹开红 译.

电子工业出版社 出版

容器使用的12条军规——《Effective+STL中文版》试读的更多相关文章

  1. Effective STL中文版 译序

    <Effective STL中文版>译序 就像本书的前两本姊妹作(Effective C++.More Effective C++)一样,本书的侧重点仍然在于提升读者的经验,只不过这次将焦 ...

  2. Effective STL 中文版(大全)

    Effective STL 中文版(大全) 作者:winter 候捷说,对于STL,程序员有三个境界,开始是使用STL,然后是理解STL,最后是补充STL.Effective STL是一本非常好的书, ...

  3. 《Effective STL中文版》前言

    <Effective STL中文版>前言     我第一次写关于STL(Standard Template Library,标准模板库)的介绍是在1995 年,当时我在More Effec ...

  4. Effective Objective-C 2.0 — 第12条:理解消息转发机制

    11 条讲解了对象的消息传递机制 12条讲解对象在收到无法解读的消息之后会发生什么,就会启动“消息转发”(message forwarding)机制, 若对象无法响应某个选择子,则进入消息转发流程. ...

  5. [置顶] Effective STL 学习笔记

    看Effective STL 作的一些笔记,希望对各位有帮助. 以下是50条条款及相关解释. 容器 1. 慎重选择容器类型,根据需要选择高效的容器类型. 2. 不要试图编写独立于容器类型的代码. 3. ...

  6. 《Effective STL》学习笔记

    http://www.cnblogs.com/arthurliu/archive/2011/08/07/2108386.html 作者:咆哮的马甲 出处:http://www.cnblogs.com/ ...

  7. Effective STL 读书笔记

    Effective STL 读书笔记 标签(空格分隔): 未分类 慎重选择容器类型 标准STL序列容器: vector.string.deque和list(双向列表). 标准STL管理容器: set. ...

  8. Effective STL 学习笔记 32 ~ 33

    Effective STL 学习笔记 32 ~ 33 */--> div.org-src-container { font-size: 85%; font-family: monospace; ...

  9. Effective STL 学习笔记: Item 22 ~ 24

    Effective STL 学习笔记: Item 22 ~ 24 */--> div.org-src-container { font-size: 85%; font-family: monos ...

随机推荐

  1. JavaScript-事件周期-点击替换颜色

    事件周期 DOM:3个阶段 1.捕获:从最外层元素,向内层元素,逐个记录绑定的事件处理函数.默认,暂不触发任何事件 2.目标触发:优先触发目标元素绑定的事件处理函数 目标元素:实际点击的元素 3.冒泡 ...

  2. 如何防止JAVA反射对单例类的攻击?

    在我的上篇随笔中,我们知道了创建单例类有以下几种方式: (1).饿汉式; (2).懒汉式(.加同步锁的懒汉式.加双重校验锁的懒汉式.防止指令重排优化的懒汉式); (3).登记式单例模式; (4).静态 ...

  3. web应用程序传递连接字符串给FastReport数据源

    public static FastReport.Report fr = new FastReport.Report(); public static FastReport.EnvironmentSe ...

  4. Java学习笔记二——标识符和关键字

    标识符 定义 标识符的定义:对各种变量.方法和类等要素命名时使用的字符序列成为标识符. 简单地说,就是凡是自己可以起名字的地方都叫标识符,都要遵守标识符的规则. 命名规则 标识符只能由字母.下划线&q ...

  5. 【摘】【网络】无线AP与无线路由器有什么区别?

    参考网站: 1.无线上网百科 http://wifi.baike.com/article-290204.html 图片 1 今天我们从功能.应用.组网和成本四个方面为大家区分无线路由器和无线AP.当前 ...

  6. Python 之 lamda 函数

    1.例子 语法:lambda [args1,argus2....]:expression map(lambda x: x*x, [y for y in range(10)]) lambda:" ...

  7. python发邮件实现Redis通知功能

    # -*- coding:utf-8 -*- import smtplib #import os from email.mime.text import MIMEText from email.mim ...

  8. centos 清理内存缓存

    读写文件时,Linux内核为了提高读写效率与速度,会将文件在内存中进行缓存,这就是Cache Memory(缓存内存).即使程序运行结束后,Cache Memory也不会自动释放.这就会导致程序频繁读 ...

  9. WPF Loaded事件连续调用两次的问题

    最近开发的一套系统中,在检查开发成员的代码时候,在Loaded事件中加上以下语句: this.Loaded -= new RoutedEventHandler(***_Loaded);这让我觉得有些奇 ...

  10. JQuery图片轮播滚动效果(网页效果--每日一更)

    今天,带来的是一个图片的轮播滚动效果! 先来看一下效果展示:亲,请点击这里 原理很简单,设置一个定时器,使图片列表在每隔一段时间后滚动一次.而循环效果,就是在每一滚动的时候,将第一张图片放到最后一张的 ...