Effective STL 读书笔记

本篇文字用于总结在阅读《Effective STL》时的笔记心得,只记录书上描写的,但自己尚未熟练掌握的知识点,不记录通用、常识类的知识点。

STL按照容器类型,可以分为标准序列容器(deque,vector,list,string),标准关联容器(map,multimap,set,multiset),另外,还有非标准容器,序列类型有slist和rope,关联类型有hash_**类相关容器。标准关联容器总是保持排列顺序。

在关联容器中,确保关联容器对于所使用的比较函数,对于相等的值,总是返回False。

在stl代码中,入参常见缩写,lhs=left hand side,rhs=right hand side。

STL对于数据的处理原则是,进入是拷贝,出来也是拷贝(有些出来是引用,需要根据实际调用函数来决定)

命名空间不要使用全部的空间,比如单个文件中用到vector,可以这样包含

#include <vector>
using std::vector

尽量减少对外部的依赖。

模板形参统一使用typename,而不使用class,因为typename可以用来重定义内部参数类型,而class不行。

C++标准规定,在抛出异常的地方,在退出之前,会调用局部对象的析构函数,确保局部对象析构完成后再退出。

派生类的构造函数、拷贝构造函数、=重载,==重载等函数在实现时,需要显示调用基类对应的函数,调用方法通过类型::函数名的方式来实现,确保派生类相关函数在语义上面的一致性。

vector可以看出是动态增值的数组,它的size为实际存储数据个数,capacity为为存储数据而分配的内存空间。每次扩容,会伴随着内存申请、容器内容拷贝和旧数据的销毁,在VS平台上的vector扩容策略为每次增加当前容量的一般。

vector的优化策略:

  1. 对于预存数据数目可预先确定的情况,可以通过预先调用reserve来分配空间,再执行push_back,这种方法比直接push_back效率高

  2. 为了减少容器类数据拷贝延迟,可以在容器中存指针

  3. 对于判空操作,使用容器自带的empty函数优于使用size函数判空

  4. 多余内存空间释放技巧 vector(dest).swap(dest)

    vector(dest)创建一个临时变量,它的内容是dest的拷贝,使用vector的拷贝构造函数(它只拷贝真实存放的变量),然后将这个临时变量里面的数据和dest作交换后,dest里面的容量恢复正常状态,临时变量的容量则为dest的容量(通常情况下很大),执行完这句话,临时变量自动析构,释放之前占据的内存,dest则shrink to fit。

map<K,v>里面的元素类型为 pair<const K, V>,这也就说明不要试图去修改map里面的K值。

map[k] = v 的含义是 添加和更新,添加操作=临时变量的默认构造函数+赋值+析构该临时对象,在更新时,效率比insert高

map.insert(v):的含义:仅仅是添加,在添加时,效率比[]高。

remove不是真正意义上的删除,它做不到,它移动区间里面的元素,其中"不用被删除"的元素移动到区间的前部(保持原来相对顺序),它返回一个迭代器,指向"之后不用被删除"的元素之后的元素,一般有erase-remove是惯用法。这其中有例外,list::remove是真正删除元素.

迭代器

输入输出迭代器,这里面的输入输出的视角是以迭代器的视角,左侧站着的是容器,中间是迭代器,右侧的是算法,输入迭代器的意思是:以迭代器为主要视角,往迭代器输入,那么对于左侧的容器来说,就是输出,也就是读取迭代器里面的内容了。

基础迭代器分为输入迭代器(同一位置只读一次)和输出迭代器(同一位置只写一次),在两者功能的基础上,衍生出前向迭代器(同一位置可重复读写,并且支持向前单步移动),在前向迭代器功能基础上,衍生出双向迭代器(支持向后单步移动,也就意味着 支持双向单步移动),在双向迭代器的基础上,衍生出随机迭代器(支持跳跃移动)

算法

使用stl的算法和循环在大多数情况下,比自己手写循环在效率、正确性、可维护性上面都更胜一筹。

使用for_each(a.begin(), a.end(), func);

这里的fun有几种各种不同的情况:

  1. func为同名本地函数,传入的是函数指针
  2. func为同名类,传入的是类的"()"操作符的重载函数
  3. func为类的成员函数,传入的是类的成员函数地址

C和C++的标准库函数遵循传递函数指针是按照传值方式来,形如方式1,在传入函数指针数值,在循环内部根据此指针去寻找确切的函数

函数对象,简单的说,就是对象,这种对象,重载了()运算符,比如 class A,那么可以像调用函数一样使用它,比如A(5),这样使用。函数对象相比于全局函数,它可以保存状态信息,

struct WidgetNameCompare:
public std::binary_function<Widget, Widget, bool>{ bool operator()(const Widget& lhs, const Widget& rhs)const;
}

一般情况下,传递给unary_function(单个入参,返回值类型)或binary_function(两个入参,返回值类型)的非指针类型需要去掉const、引用和入参变量名称。

如果是带指针的入参,则需要如以下来定义:

struct PtrWidgetNameCompare:

public std::binary_functon<const Widget, const Widget, bool>{

bool operator()(const Widget* lhs, const Widge* rhs)const;

}

针对第三种情况,传入判别式为类的成员函数时,根据当前容器类型,如果当前容器里面存储的是类实例时,使用mem_fun_ref包装类成员函数,使其适配for_each的调用格式。当当前存储的是类实例指针时,使用mem_fun来包装.

使用函数对象而不是函数作为STL算法参数,是因为函数指针作为参数会抑制内联优化,而函数对象不会.

算法的名称含义

transform算法:某个函数将被应用到一个区间中的每一个对象,并把调用结果写到某一个地方。

replace_if算法:区间中所有满足判别式条件的对象都将被修改。

partition算法:一个区间中的对象将会被移动,所有满足某个判别式条件的对象会被组织到一起。

在有序序列中,可以使用lower_bound(查找第一次出现4的地方) , upper_bound(查找最后一个出现4的地方的后一个位置),equal_range相当于 lower_bound+upper_bound。

	     lower_bound(first,last,4)
1-->2-->3 -->4-- >4-->4-->4 -->5- ->6-->7--->8
upper_bound(first,last,4)

stl提供了在有序序列中的二分查找算法 binary_search

在算法调用和手写循环中,关于代码清晰度取决于你要在循环中做什么事情,如果要做的事情和一个算法实现的功能很相近,那么用算法调用会更好。

在软件工程领域中,一份代码被阅读的次数要远远大于它被编写的次数,可读性、可维护性需要特别注意。

Effective STL读书笔记的更多相关文章

  1. Effective STL 读书笔记

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

  2. effective stl读书笔记 & stl里面提供的算法 & emplace & ostream_iterator

    加锁和解锁,也可以在构造函数和析构函数里面,自动调用. 相等和等价的关系:等价是用在排序的时候,跟less函数有关. vector,deque,string 要用erase-remove组合:而关联容 ...

  3. Effective STL 学习笔记 39 ~ 41

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

  4. Effective STL 学习笔记 Item 38 : Design functor classes for pass-by-value

    Effective STL 学习笔记 Item 38 : Design functor classes for pass-by-value */--> div.org-src-container ...

  5. Effective STL 学习笔记 Item 34: 了解哪些算法希望输入有序数据

    Effective STL 学习笔记 Item 34: 了解哪些算法希望输入有序数据 */--> div.org-src-container { font-size: 85%; font-fam ...

  6. Effective STL 学习笔记 32 ~ 33

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

  7. Effective STL 学习笔记 31:排序算法

    Effective STL 学习笔记 31:排序算法 */--> div.org-src-container { font-size: 85%; font-family: monospace; ...

  8. Effective STL 学习笔记 Item 30: 保证目标区间足够大

    Effective STL 学习笔记 Item 30: 保证目标区间足够大 */--> div.org-src-container { font-size: 85%; font-family: ...

  9. Effective STL 学习笔记 Item 26: Prefer Iterator to reverse_iterator and const_rever_itertor

    Effective STL 学习笔记 Item 26: Prefer Iterator to reverse_iterator and const_rever_itertor */--> div ...

随机推荐

  1. 线程安全的无锁RingBuffer的实现【一个读线程,一个写线程】

    在程序设计中,我们有时会遇到这样的情况,一个线程将数据写到一个buffer中,另外一个线程从中读数据.所以这里就有多线程竞争的问题.通常的解决办法是对竞争资源加锁.但是,一般加锁的损耗较高.其实,对于 ...

  2. 09Vue.js快速入门-Vue入门之Vuex实战

    9.1. 引言 Vue组件化做的确实非常彻底,它独有的vue单文件组件也是做的非常有特色.组件化的同时带来的是:组件之间的数据共享和通信的难题. 尤其Vue组件设计的就是,父组件通过子组件的prop进 ...

  3. 出去html中的标签

    C#写法 public static string StripHTML(string strHtml) { string strOutput = strHtml; Regex regex = new ...

  4. webbrowser取页面验证码

    碰到一个无比坑爹,外加蛋疼乳酸的问题.从昨天晚上发现bug,到今天下午解决问题,搞了大半天的时间.光是找问题就花了半天,解决问题的方法简单,但是方案的形成也是无比纠结的过程. 背景:webbrowse ...

  5. 汉字转拼音首字母的java实现

    工作中经常会遇到的一些排序问题,比如 按汉字的拼音首字母排序,比如人名排序等,就要用到下面的方法了,思路: 1. 获得汉字 2. 将汉字转换成首字母,并记录下(必要时保存到数据库) 3. 按首字母进行 ...

  6. 放弃winform的窗体吧,改用html作界面,桌面应用程序UI的新的开发方式。

    做过很多winform项目,都为winform控件头疼不已.想实现一些漂亮的样子总是很难.我这里列举几个缺点: 1.winform控件大多是 绝对布局 ,你需要给出准确的坐标.那么在实现居中效果就会很 ...

  7. EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.

    启动两个client,过了一会,停了其中一个,访问注册中心时,界面上显示了红色粗体警告信息: 查阅了很多资料,终于了解了中间的问题.现将理解整理如下: Eureka server和client之间每隔 ...

  8. SpringBoot使用端口运行

    通过java -jar app.jar --name="Spring" --server.port=9090方式来传递参数. 参数用--xxx=xxx的形式传递. 转自http:/ ...

  9. CRNA的使用

    为了能让更多人感受 RN 的魅力,早在几个月前 React-community 就给出了一个不错的解决方案,可以让一个完全没接触过 RN 的人,从配环境开始5分钟实现 Hello Wolrd 的编写( ...

  10. 关于Unity中变量和函数的定义

    变量 1.匀速运动的物体都要记得定义一个speed速度变量 2.不断产生很多相同物体的事件要记得定义时间生成物体的间隔rate,并且有一个一达到rate的值就清0的累加时间变量,累加时间变量是通过Ti ...