C++ Primer学习笔记(第9章-第11章)
const使用总结
-
const修饰变量,表示该变量为常量,必须在定义是初始化,且不能修改它的值。
-
const修饰指针:
-
const int *ip = &val:ip是指向const对象(int)的指针,即不能通过(*ip)修改val的值(如果val不是const常量,可以通过其他方式修改val的值);
-
int *const ip = &val:ip是指向int对象的const指针,即不能修改ip的值,但(*ip)的值可以修改;
-
const int *const ip=&val:ip是指向const对象的const指针。
-
-
Const修饰函数:const int& op(const int) const
-
const修饰返回值,表示返回值不能修改,只有在返回引用类型时才有效(不能返回局部对象的引用);
-
const修饰参数,表示该参数不能在函数中修改。需要注意的是参数是指针的情况,到底是const指针还是指向const对象的指针;
-
const修饰函数:const修饰类的成员函数时,表示该函数不能修改类的成员变量。
-
-
第9章 顺序容器
-
关联容器和顺序容器的本质区别在于:关联容器通过键(key)存储和读取元素,而顺序容器的元素排列次序与元素值无关,是由元素添加到容器里的次序决定。
-
标准库定义了三种顺序容器类型:vector, list 和 deque。vector是连续存储的,能支持快速随机访问;list不需要连续存储,所以能在中间快速插入和删除;deque是双端队列。标准库还提供了三种容器适配器:后进先出的stack、先进先出的queue和有优先级管理的priority_queue。stack可以建立在vector、list、deque上,queue要能提供push_front操作,不能建立在vector上,priority_queue要求提供随机访问能力,只能建立在vector或deque上。
-
定义元素是容器的容器时,必须用空格隔开两个相邻的>符号,以示这是两个分开的符号,否则,系统会认为>>是单个符号,为右移操作符,并结果导致编译时错误;
example:vector< vector<string> > lines;
-
容器元素类型必须满足两个约束:
-
元素类型必须支持赋值运算
-
元素类型的对象必须可以复制
-
引用不支持一般意义的赋值运算,IO标准库类型不支持赋值和复制操作,所以不能创建存储他们的容器。
-
顺序容器上的操作
-
初始化(适用于关联容器)
-
C<T> c默认初始化,创建一个空的容器
-
C c(c2) 创建容器c2的副本c,两个容器的类型和元素类型都必须相同
-
C c(b,e) 创建c,其元素是迭代器b和c标示的范围内元素的副本,只要迭代器存储的值能转化为容器的元素即可,不需要容器类型相同。
-
C c(n,t) / C c(n) 创建有n个值为t(或默认值)的容器c,只适用于顺序容器。
-
-
向容器内添加元素
-
有三类函数push_back()、push_front()、insert(),用insert()在指定位置插入单个元素时,返回指向新元素的迭代器,其他的都返回void
-
容器大小操作
size(), max_size(), empty() resize()。resize()能删除多出来的元素。
-
访问元素
用迭代器迭代容器或者使用下标操作(list不支持下标操作)
-
删除元素
erase()(返回指向删除元素后的迭代器), clear(), pop_back(), pop_front() (pop_操作只删除元素,不返回删除的元素值,返回void)
-
assign赋值操作 , swap 交换容器操作(不会破坏迭代器)
-
list vs vector deque
-
list的元素不是连续存储,所以不支持随机访问,所以不支持下标操作([])和at()操作,其上的迭代器不支持 +n 操作和大小比较操作(进支持等于,不等操作)
-
vector不支持前端操作(push_front() pop_front())
-
-
修改容器时,会使容器上的迭代器失效。vector和deque连续存储,在中间插入删除元素时,会重组织存储。
-
string类型不支持以栈方式操纵容器;string支持的其他操作:substr append replace find compare 。
第10章 关联容器
-
标准库提供的关联容器有:map,set,multimap, multiset。map存储键值对,set存储单个键,multi支持同一个见多次出现。
-
pair类型和make_pair函数:对map上的迭代器解引用是pair<cont T1, T2>对象。
-
map、set上的键类型,唯一的约束就是必须支持<操作符,至于是否支持其他的关系或相等运算,则不做要求。
-
map,set,multimap,multiset
-
都支持insert,count,find,erase操作以及lower_bound,upper_bound, equal_range操作(注意他们的返回值),初始化见顺序容器;
-
只有map支持下标操作,而且与下标访问数组或vector的行为截然不同:用下标访问不存在的元素将导致在map容器中添加一个新元素,它的键即为该下标值,值为值类型的默认初始化值。
-
第11章 泛型算法
-
泛型算法中,所谓“泛型“指的是两个方面:这些算法可作用与各种不同的容器类型,而这些容器又可以容纳多种不同的元素。泛型算法必须包含<algorithm>头文件,算术算法还必须包含<numerc>头文件。插入器(inserter)包含在<interator>头文件中。
-
泛型算法的形参模式: alg (beg, end, beg2, end2, other parms)、
beg,end标记第一个范围,这两个参数泛型算法都有;beg2,end2标记第二个范围,可能没有这个两个参数;parms表示其他算法需要的值或谓词。
-
算法不直接修改容器的大小,如果需要添加和删除元素,则必须使用容器操作。
-
泛型算法的分类
-
只读算法:只读输入范围内的元素,而不会写这些元素。find(), accumulate(), find_first_of()是只读算法;
-
写容器元素算法:将数据写入第一或第二输入范围。find(), find_n(), copy(), replace() 都是这类算法。直接将元素写入目标很危险,因为泛型算法不会调用容器提供的操作(如insert)(相当于用下标读vector的内容,再修改),所以很类算法一般要和插入迭代器配合使用。有三种插入迭代器:back_inserter,创建使用push_back实现插入的迭代器;front_inserter,使用push_front实现插入(不能用在vector上);inserter,使用insert实现插入。
-
vector<int> ivec;
replace_copy(ilist.begin(), ilist.end(), inserter(ivec,ivec.begin), 0, 42);
-
对容器元素重新排序的算法:sort(), unique()
-
五种迭代器
-
输入迭代器:读,不能写;只支持自增运算。istream_iterator是输入迭代器
-
输出迭代器:写,不能读;只支持自增运算。ostream_iterator是输出迭代器
-
前向迭代器:读和写,只支持自增运算。replace算法需要前向迭代器
-
双向迭代器:读和写,支持自增和自减运算,map、set、list提供双向迭代器。Reverse算法需要双向迭代器
-
随机访问迭代器:读和写,支持完整的迭代器算术运算,string、vector和deque提供双向迭代器。
-
-
list容器特有的算法
list上提供双向迭代器,故很多需要随机访问迭代器的算法不能在其上运行,故标准库为list容器定义了更精细的操作集合,如merge(), remove(), sort(), reverse(), splice(), unique()