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 ...
随机推荐
- [转载]为何 Emacs 和 Vim 被称为两大神器
Emacs 是神的编辑器,而 Vim 是编辑器之神.二者为何会有如此美誉,且听本文向你一一道来. 目 录 0. 序章:神器的传说 1. 无敌的可扩展性 1.1 可扩展性给了软件强大的生命 1.2 Em ...
- IOS 地图移动中心点获取
MKMap显示地图后,如果用户移动了地图,自己定义的数据就需要刷新了,所以这个时候,中心点的经纬度就比较重要了. 本文演示如何获取经纬度 在MKMapViewDelegate里有个方法 - (void ...
- angular 兼容ie7 bootstrap2兼容ie6
http://stackoverflow.com/questions/12709745/angular-routing-not-working-in-ie7/12891208#12891208
- Android——Android Studio导入SlidingMenu类库的方法
Android Studio导入SlidingMenu类库的方法(其他类库应该也适用) 本篇文章主要介绍了"Android Studio导入SlidingMenu类库的方法(其他类库应该 ...
- redis详细配置文件
redis 单机版自己指定配置 #修改为守护模式 daemonize yes #设置进程锁文件 pidfile /usr/local/redis/redis.pid #端口 port 6379 #客户 ...
- Entity Framework应用:EntityFramework DataBase First模式
在这篇文章中讲解如何使用EF的DbFirst模式实现数据的增删改查 一.新建控制台应用程序,然后右键->添加新建项,选择数据里面的实体数据模型: 然后点击添加 二.选择来自数据库的EF设计器,并 ...
- SpringBoot2 集成三种连接池 c3p0 hikari druid
Hikari 1.首先集成 hikari springboot默认集成,只需要简单的配置即可 1.1 首先导入包 <dependency> <groupId>com.zaxxe ...
- 优雅的运用 Kotlin 的 null safety 特性,而不要简单的直接用 !!双感叹号
对于 Null 的检查是 Kotlin 的特点之一.强制你在编码过程中考虑变量是否可为 null,因此可以避免很多在 Java 中隐藏的 NullPointerException. 但是,当你用插件直 ...
- GCC编译错误小结
gcc编译时对’xxxx’未定义的引用问题可能错误 错误一: 没有实现xxxx 错误二: c++引用c语言so库,但是so库头文件没有extern "C" 错误三: 检查各个共享库 ...
- WDCP面板V3新版本安装与体验记录
WDCP面板V3版本看介绍变动还是比较大的,比如从底层重新架构,以及我们需要的PHP.MYSQL.NGINX等版本都是使用较新稳定版本,支持CENTOS5-7发行版本环境,至于后台界面的友好度有点扁平 ...