该博客用于记录自己在阅读过程中不懂的知识点,很少用到但比较重要的知识点以及模棱两可的知识点
顺序容器类型:
vector //可变大小数组,快速随机访问,尾部以外的地方插入 删除可能会很慢deque //双端队列,快速随机访问,头尾插入删除很快
list //双向链表,只支持双向顺序访问,任何位置插入删除 都很快
forward_list //单向链表,只支持单向顺序访问,任何位置插入删除 都很快
array //固定大小数组,快速随机访问,不能添加和删除
string //与vector相似,专用于保存字符
当构造一个容器时,其中的元素类型没有构造函数,那就不能只接受一个容器大小参数,应该给予一个元素初始化器(印证了前面所说容器里面的元素都要初始化):
vector<noDefault> v1(10, init);
vector<noDefault> v2(10); //错误,noDefault类型没有默认构造 函数,必须提供一个元素初始化器
容器操作:
类型别名:
iterator/const_iterator //此容器类型的迭代器
size_type //用于保存容器大小,无符号整型
difference_type //用于保存两个迭代器之间的距离,带符号整型
value_type //元素类型
reference/const_reference //元素的左值类型,value_type &
构造函数:
C c;
C c1(c2);
C c(b, e); //构造C,迭代器b和e指定范围内的元素拷贝到c,不 支持array
C c{a, b, c, d…}
赋值与swap
c1 = c2
c1 = {a, b, c, d…}
a.swap(b)
swap(a, b)
大小
c.size() //不支持forward_list
c.max_size() //可保存的最大元素数量
c.empty()
添加删除元素
c.insert(args) //将args中的元素拷贝进c
c.emplace(init) //使用init构造c中的一个元素
c.erase(args)
c.clear()
关系运算符
==、!=
<, <=, >, >=
获取迭代器
c.begin()/c.end()
c.cbegin()/c.cend()
反向容器的额外成员
reverse_iterator/const_iterator //逆序
c.rbegin()/c.rend() //尾和首
c.crbegin()/c.crend() //只读
array的大小也是类型的一部分
array<int 42>
执行赋值运算后,如果两容器大小不同,则会统一为右边的大小
赋值运算可以使用assign(不适用与关联容器和array),能将不同但相容的类型赋值,例
list<string> name;
vector<const char*> oldstyle;
names = oldstyle; //错误,容器类型不匹配
names.assign(oldstyle.cbegin(), oldstyle.cend()); //正确,将const char* 转换为string
swap并未交换元素,而只是交换了两容器的内部数据结构,从书上目前理解来说,我认为可以理解为只是改了个名字,例如iter是指向一个含有 10个元素的容器A,当容器A与容器B swap过后,原来依附于A的iter,改为依附于B(其实没有改变依附对象,只是A的名字换为B了),所以可以保证常数时间内完成,且容器内部的迭代器,引用,指针不会失效(assign会),先暂时这样理解,看完《STL源码剖析》后,如果错了再来更改
有个特例是array,swap会真正意义上的交换容器中的元素,但迭代器,指针,引用绑定的位置不变,也就是说,只是值变了,又因为array的规格也是类型的一部分,所以不用担心交换过后迭代器等指向不存在的位置
关系运算符两边的容器及容器内的元素都必须相同
比较时比第一个不同的元素的大小,再比规格
实际上容器的比较是用元素的比较运算符来实现的,相等运算符是用元素的==运算符实现的,其他关系运算符是用<运算符实现的
向顺序容器添加元素
forward_list有自己专有的insert和emplace,不知道push_back和emplace_back
vector和string不支持push_front和emplace_front,上文中有提到,这个两个容器适合在尾部添加元素
c.push_back(t)
c.emplace_back(init)
c.push_front(t)
c.emplace_front(init)
c.insert(p, t) //再迭代器p前添加元素,反回指向新添加元素的 c.emplace(p, init) 迭代器
c.insert(p, n, t) //在迭代器p前添加n个t元素,返回指向添加的第 一个元素的迭代器
c.insert(p, b, e) //将迭代器b和e之间的元素添加到迭代器p指向 元素之前,返回添加的第一个元素
c.insert(p, i1) //i1是一个值列表
向vector string deque插入元素会使所有指向该容器的迭代器,指针,引用失效
假定一个容器vector<testclass> vec,其中testclass是一个类,它的构造函数需要三个整型参数,我们可以这样使用emplace_back:
vec.emplace_back(1, 2, 3);
他会自动调用testclass的构造函数,而使用push_back时传进去的就必须是一个元素,我们可以创建一个临时对象来加入vec
vec.push_back(testclass(1, 2, 3));
顺序容器有back(forward_list没有)和front成员函数,返回元素的引用,begin和end返回的迭代器需要解引用
c[n]和c.at(n);
顺序容器删除元素
forward_list有特殊版本的erase且不支持pop_back; vector和string不支持pop_front
c.pop_back()
c.pop_front()
c.erase(p) //删除p迭代器所指元素,返回p迭代器后一个元素的 迭代器
c.erase(b, e)
c.clear()
删除deque除首尾元素之外的任何元素都会使迭代器,指针,引用失效,指向vector和string删除点之后的迭代器,引用指针失效
因为foward是一个单向链表,没有好的方法类获取某个元素的前驱,所以一般是通过操作给定元素之后的元素来完成的(因此它有一个叫做首前的迭代器),所以它有一套独立的添加和删除操作:
lst.before_begin()/lst.cbefore_begin() //指向首元素之前不存在的元素的 迭代器
lst.insert_after(p, t) //p位置后添加元素t,返回一个指向插入的最后 一个元素的迭代器
lst.insert_after(p, n, t)
lst.insert_after(p, b, e)
lst.insert_after(p, i1)
emplace_after(p, init)
lst.erase_after(p) //删除p之后的所有元素,返回指向被删除元素 的后一个元素的迭代器
lst.erase_after(b, e) //(b, e]
resize可以改变容器大小,当前大小大于新的大小,则会删除多出来的,当前大小小于新的大小,则会将新元素添加到容器后部,如果新元素没指定,则默认初始化
end()操作很快,循环时如果做了某些操作,可能会使end()返回的迭代器失效,所以好的办法是每次斗重新计算end()
vector和string 分配内存时通常会分配比需求更大的空间,多出来的这部,就用来备用,就避免了每次添加新元素都要做分配内存这种低效率的工作
容器空间管理操作
shrink_to_fit 只适用于vector string deque
capacity和reserve只适用于vector和string
c.shrink_to_fit() 将capacity减少为和size一样的大小,即缩小让容器 饱和
c.capacity() c当前可以保存多少元素
c.reserve(n) 分配至少能容纳n个元素的空间,当前容量小于等于n 什么也不做
构造string的其他方法
string s(cp, n) s是cp前n个字母的拷贝
string s(s2, pos2) s是s2从pos位置开始到结束的拷贝
string s(s2, pos2, len2)
string的一系列修改操作
string搜素操作
s.find(s1) //返回s中第一次出现s1的下标
s.find_first_of(s1) //返回s中第一次出现s1所含字符的位置
s.find_last_of(s1)
s.find_first_not_of(s1)
s.find_last_not_of(s1)
s.rfind //逆向搜索
compare的几种参数形式
string s = to_string(i) //整数转string
double d = stod(s) //字符串转浮点数
stoi
stol
stoul
stoll
stoull
stof
stod
stold
stack可以由array和forward_list之外的容器来构造,因为它要求有push_back,pop_back,back操作,对应于stack的操作是,push(),pop(),top()
queue可以由list和deque来构造,因为它需要push_back,front,pop_front操作, pop(),front(),back(),push()
priority_queue可以由vector和deque构造,因为它除了要有queue的能力之外还要求能随机访问,pop(), top(),push()
当这些适配器基于某种容器构造时,需要加上容器的类型和容器内元素的类型
stack<string, vector<string>> str_stk