Effective STL读书笔记
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的优化策略:
对于预存数据数目可预先确定的情况,可以通过预先调用reserve来分配空间,再执行push_back,这种方法比直接push_back效率高
为了减少容器类数据拷贝延迟,可以在容器中存指针
对于判空操作,使用容器自带的empty函数优于使用size函数判空
多余内存空间释放技巧 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有几种各种不同的情况:
- func为同名本地函数,传入的是函数指针
- func为同名类,传入的是类的"()"操作符的重载函数
- 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读书笔记的更多相关文章
- Effective STL 读书笔记
Effective STL 读书笔记 标签(空格分隔): 未分类 慎重选择容器类型 标准STL序列容器: vector.string.deque和list(双向列表). 标准STL管理容器: set. ...
- effective stl读书笔记 & stl里面提供的算法 & emplace & ostream_iterator
加锁和解锁,也可以在构造函数和析构函数里面,自动调用. 相等和等价的关系:等价是用在排序的时候,跟less函数有关. vector,deque,string 要用erase-remove组合:而关联容 ...
- Effective STL 学习笔记 39 ~ 41
Effective STL 学习笔记 39 ~ 41 */--> div.org-src-container { font-size: 85%; font-family: monospace; ...
- 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 ...
- Effective STL 学习笔记 Item 34: 了解哪些算法希望输入有序数据
Effective STL 学习笔记 Item 34: 了解哪些算法希望输入有序数据 */--> div.org-src-container { font-size: 85%; font-fam ...
- Effective STL 学习笔记 32 ~ 33
Effective STL 学习笔记 32 ~ 33 */--> div.org-src-container { font-size: 85%; font-family: monospace; ...
- Effective STL 学习笔记 31:排序算法
Effective STL 学习笔记 31:排序算法 */--> div.org-src-container { font-size: 85%; font-family: monospace; ...
- Effective STL 学习笔记 Item 30: 保证目标区间足够大
Effective STL 学习笔记 Item 30: 保证目标区间足够大 */--> div.org-src-container { font-size: 85%; font-family: ...
- 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 ...
随机推荐
- 线程安全的无锁RingBuffer的实现【一个读线程,一个写线程】
在程序设计中,我们有时会遇到这样的情况,一个线程将数据写到一个buffer中,另外一个线程从中读数据.所以这里就有多线程竞争的问题.通常的解决办法是对竞争资源加锁.但是,一般加锁的损耗较高.其实,对于 ...
- 09Vue.js快速入门-Vue入门之Vuex实战
9.1. 引言 Vue组件化做的确实非常彻底,它独有的vue单文件组件也是做的非常有特色.组件化的同时带来的是:组件之间的数据共享和通信的难题. 尤其Vue组件设计的就是,父组件通过子组件的prop进 ...
- 出去html中的标签
C#写法 public static string StripHTML(string strHtml) { string strOutput = strHtml; Regex regex = new ...
- webbrowser取页面验证码
碰到一个无比坑爹,外加蛋疼乳酸的问题.从昨天晚上发现bug,到今天下午解决问题,搞了大半天的时间.光是找问题就花了半天,解决问题的方法简单,但是方案的形成也是无比纠结的过程. 背景:webbrowse ...
- 汉字转拼音首字母的java实现
工作中经常会遇到的一些排序问题,比如 按汉字的拼音首字母排序,比如人名排序等,就要用到下面的方法了,思路: 1. 获得汉字 2. 将汉字转换成首字母,并记录下(必要时保存到数据库) 3. 按首字母进行 ...
- 放弃winform的窗体吧,改用html作界面,桌面应用程序UI的新的开发方式。
做过很多winform项目,都为winform控件头疼不已.想实现一些漂亮的样子总是很难.我这里列举几个缺点: 1.winform控件大多是 绝对布局 ,你需要给出准确的坐标.那么在实现居中效果就会很 ...
- 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之间每隔 ...
- SpringBoot使用端口运行
通过java -jar app.jar --name="Spring" --server.port=9090方式来传递参数. 参数用--xxx=xxx的形式传递. 转自http:/ ...
- CRNA的使用
为了能让更多人感受 RN 的魅力,早在几个月前 React-community 就给出了一个不错的解决方案,可以让一个完全没接触过 RN 的人,从配环境开始5分钟实现 Hello Wolrd 的编写( ...
- 关于Unity中变量和函数的定义
变量 1.匀速运动的物体都要记得定义一个speed速度变量 2.不断产生很多相同物体的事件要记得定义时间生成物体的间隔rate,并且有一个一达到rate的值就清0的累加时间变量,累加时间变量是通过Ti ...