C++复习笔记
c++ primer笔记
顺序容器(二)
关于容器的选择
元素是否是连续存储还会显著的影响:
a)在容器的中间位置添加或删除元素的代价。
b)执行容器元素的随机访问的代价。
程序使用这些操作的程度将决定应该选择哪种类型的容器。vector和deque容器提供了元素的快速随机访问,但是代价是,在容器的任意位置插入或删除元素,比在容器尾部插入和删除的开销更大。list类型在任何位置都能快速插入和删除,但付出的代价是元素的随机访问开销较大。
- 插入操作对于容器选择的影响
list容器表示不连续的内存区域,允许向前和向后逐个遍历元素。在任何位置都可以高效的insert(插入)或erase(删除)一个元素。而且插入或删除list容器中的一个元素不需要移动任何其他元素。另一方面,list容器不支持随机访问,访问某个元素要求遍历所涉及的其他元素。
对于vector容器,除了容器尾部之外,其他任何位置上插入或删除都要求移动被插入或者删除位置右边的所有元素。
对于deque容器,其拥有更加复杂的数据结构。从deque队列的两端插入和删除元素都非常快。但是在容器中间插入或删除元素的代价也更高。deque容器同时具有list和vector的一部分性质:
a)和vector容器一样,在deque容器中间插入和删除元素的效率比较低。
b)不同于vector容器,deque容器提供了高效地在其头部实现的插入和删除操作,和在尾部操作同样的效率。
c)与vector容器相同但是不同于list容器的是,deque容器支持对所有元素的随机访问。
d)在deque容器的首部或者尾部插入元素不会使任何迭代器失效,而在首部或尾部删除元素则指挥使只想被删除元素的迭代器失效。而在deque容器的任何其他位置的插入和删除操作将使指向该容器元素的所有迭代器都失效。
- 元素访问对于容器选择的影响
vector和deque容器都支持对其元素实现高效的随机访问。list容器中,元素之间移动的唯一方法是顺序跟随指针。
通常来说,除非找到选择使用其他容器的更好理由,否则vector容器都是最佳选择。
- 选择容器的原则
选择容器一般要符合以下的原则:
a)如果程序要求随机访问元素,则应使用vector或deque容器。
b)如果程序必须在容器的中间位置插入或删除元素,则赢使用list容器。
c)如果不是在容器的中间位置,而是在容器首部或者尾部插入或删除元素,则应采用deque容器。
d)如果秩序在读取输入时在容器中间位置插入元素,然后需要随机访问元素,则可考虑在输入时将元素读入到一个list容器,接着对此容器重新排序,使其适合顺序访问,然后将排序后的list容器复制到一个vector容器中。
如果无法确定某种采用哪种容器,则编写代码时尽量只使用vector和list都提供的操作,例如使用迭代器而不是下标,避免随机访问元素。
string类型(二)
- 构造string对象的其他方法
char *cp = "Hiya";
char c_carry[] = "World!!!!";
char no_null[] = {'H','i'};
string s1(cp); //s1为“Hiya”
string s2(c_carry, 5); //s2为"World"
string s3(c_carry + 5, 4); //s3为"!!!!"
string s4(no_null); //error
string s5(no_null, 2); //s5为"Hi"
表达式 | 功能 |
---|---|
string s(cp, n) | 创建一个string对象,它被初始化为cp指向数组的前n个元素的副本 |
string s(s2, pos2) | 创建一个string对象,它被初始化为一个已存在的string对象s2中从下标pos2开始的字符的副本 |
string s(s2, po2, len2) | 创建一个string对象,它被初始化为s2中从下标pos2开始的len2个字符的副本。无论len2的值是多少,最多只能复制s2.size() - pos2个字符 |
string s6(s1, 2); //s6为"ya"
string s7(s1, 0, 2); //s7为"Hi"
string s8(s1, 0, 8); //s8为"Hiya"
- 修改string对象的其他方法
string类型支持的许多容器操作在操作时都是以迭代器为基础。
项目 | Value |
---|---|
s.insert(p, t) | 在迭代器p指向元素之前插入一个值为t的元素。返回指向新插入元素的迭代器 |
s.insert(p, n, t) | 在迭代器p指向的元素之前插入n个值为t的新元素,返回void类型 |
s.insert(p, b, e) | 在迭代器p指向的元素之前插入迭代器b和e标记范围内所有的元素。返回void类型 |
s.assign(b, e) | 用迭代器b和e标记范围内的元素替换s。对于string类型,该操作返回s。对于容器类型,返回void类型。 |
s.assign(n, t) | 用n个值为t的元素副本替换s。对于string类型,该操作返回s。对于容器类型,返回void类型。 |
s.erase( p) | 删除迭代器p指向的元素。返回一个迭代器,指向被删除元素后面的元素 |
s.erase(b, e) | 删除迭代器b和e标记范围内所有的元素。返回一个迭代器,指向被删除元素段后面的第一个元素 |
- 只适用于string类型的操作
以下三种操作仅支持string类型
a)substr函数,返回当前string对象的字串
b)append和replace函数,用于修改string对象
c)find函数,用于查找string对象
表达式 | 功能 |
---|---|
s.substr(pos, n) | 返回一个string类型的字符串,包含从下标pos开始的n个字符 |
s.substr(pos) | 返回一个string类型的字符串,包含从下标pos到s末尾的所有字符 |
s.substr | 返回s的副本 |
表达式 | 功能 |
---|---|
s.append(args) | 将args串接在s后面。返回s的引用 |
s.replace(pos, len, args) | 删除s中从下标pos开始的len个字符,用args指定的字符替换之。返回s的引用。 |
s.repalce(b, e, args) | 删除迭代器b和e标记范围内的所有字符,用args替换之。返回s的引用。 |
append和replace的参数args
表达式 | 功能 |
---|---|
s2 | string对象s2 |
s2, pos2, len2 | 字符串s2中从下标pos2开始的len2个字符 |
cp | 指针cp指向以空字符结束的数组 |
cp, len | cp指向的以空字符结束的数组中前len2个字符 |
n, c | 字符c的n个副本 |
b2, e2 | 迭代器b2和e2标记的范围内的所有字符 |
容器适配器
标准库中定义了三种顺序容器适配器:queue、priority_queue和stack。本质上,适配器是使一个事物的行为类似于另一事物的行为的一种机制。容器适配器让一种已存在的容器类型采用另一种不同的抽象类型的工作方式实现。例如,stack(栈)适配器可是任何一种顺序容器以栈的方式工作。