第9章 顺序容器
  1. 顺序容器和关联容器
    顺序容器内的元素按其位置存储和访问。
    关联容器,其元素按键(key)排序。
  2. 顺序容器(sequential container)。
    顺序容器的元素排列次序与元素值无关,而是由元素添加到容器里的次序决定。
  3. 标准库定义了三种顺序容器类型:vector、list 和 deque(是双端队列“double-ended queue”的简写,发音为“deck”)。
    头文件如下:
    #include <vector>
    #include <list>
    #include <deque>
  4. 标准库还提供了三种容器适配器(adaptors)。适配器是根据原始的容器类型所提供的操作,通过定义新的操作接口,来适应基础的容器类型。
    顺序容器适配器包括 stack、queue 和 priority_queue 类型。
  5. 顺序容器
    vector 支持快速随机访问,支持下标访问 ,但在中间随机插入/删除速度慢
    list   支持快速插入/删除,不支持随机访问。
    deque   双端队列
     

    顺序容器适配器

    stack
    后进先出(LIFO)堆栈
    queue 
    先进先出(FIFO)队列
    priority_queue 
    有优先级管理的队列 
  6. 所有的容器都是类模板:
    vector<string>    svec;       // empty vector that can hold strings
    list<int>         ilist;      // empty list that can hold ints
    deque<Sales_item> items;      // empty deque that holds Sales_items
  7. 容器元素的初始化(构造函数)
    容器类型最常用的构造函数是默认构造函数。在大多数的程序中,使用默认构造函数能达到最佳运行时性能,并且使容器更容易使用。
    C<T> c; 创建一个名为 c 的空容器。C 是容器类型名,如 vector,T 是元素类型,如 int 或 string 适用于所有容器
    C c(c2);  创建容器 c2 的副本 c;c 和 c2 必须具有相同的容器类型,并存放相同类型的元素。适用于所有容器。要求容器类型和容器里元素的类型都必须相同。
    C c(b, e); 创建 c,其元素是迭代器 b 和 e 标示的范围内元素的副本。适用于所有容器。不要求容器类型相同,容器里元素类型也可以不相同,相互兼容即可。
    C c(n, t);      用 n 个值为 t 的元素创建容器 c,其中值 t 必须是容器类型 C 的元素类型的值,或者是可转换为该类型的值。 只适用于顺序容器。
    C c(n); 创建有 n 个值初始化(第 3.3.1 节)(value-initialized)元素的容器 c。 只适用于顺序容器。
     
  8. 将一个容器初始化为另一个容器的副本。 
    vector<int> ivec;
    vector<int> ivec2(ivec);   // ok: ivec is vector<int> 
    将一个容器复制给另一个容器时,容器类型元素类型都必须相同。
  9. 初始化为一段元素的副本。
    不能直接将一种容器内的元素复制给另一种容器,但允许通过传递一对迭代器间接实现该实现该功能。
    使用迭代器时,不要求容器类型相同,容器内的元素类型也可以不相同,只要它们相互兼容,能够将要复制的元素转换为所构建的新容器的元素类型,即可实现复制。 
    list<string> slist(svec.begin(), svec.end());

    指针就是迭代器,因此允许通过使用内置数组中的一对指针初始化容器。
    char *words[] = {"stately", "plump", "buck", "mulligan"};
    size_t words_size = sizeof(words)/sizeof(char *);
    list<string> words2(words, words + words_size);

  10. 分配和初始化指定数目的元素
    创建顺序容器时,可显式指定容器大小和一个(可选的)元素初始化式。容器大小可以是常量或非常量表达式,元素初始化则必须是可用于初始化其元素类型的对象的值:
    const list<int>::size_type list_size = 64;
    list<string> slist(list_size, "eh?"); // 64 strings, each is eh?
    这段代码表示 slist 含有 64 个元素,每个元素都被初始化为“eh?”字符串。
    也可以只指定容器大小: 
    list<int> ilist(64); // 64 elements, each initialized to 0
  11. 容器内元素的类型约束
    容器元素类型必须满足以下两个约束:
    •  元素类型必须支持赋值运算。
    •  元素类型的对象必须可以复制。
    关联容器的键还必须支持“<”操作符。

  12. 容器的容器
    可定义元素是容器类型的容器:vector< vector<string> > lines; //必须用空格隔开两个相邻的 > 符号。
  13. 常用迭代器的运算
    *iter                                返回迭代器 iter 所指向的元素的引用 
    iter->mem 对 iter 进行解引用,获取指定元素中名为 mem 的成员。等效于(*iter).mem 
    ++iter,iter++ 给 iter 加 1,使其指向容器里的下一个元素 
    --iter,iter-- 给 iter 减 1,使其指向容器里的前一个元素
    iter1 == iter2,
    iter1 != iter2
    比较两个迭代器是否相等(或不等)。当两个迭代器指向同一个容器中的同一个元素,或者当它们都指向同一个容器的超出末端的下一位置时,两个迭代器相等 
     
  14. vector 和 deque 容器的迭代器独有支持:迭代器算术运算:iter + n , iter - n , iter1 += iter2, iter1 -= iter2,  
    除了 == 和 != 之外的关系操作符来: > , >=, < , <=
  15. list迭代器不支持算术运算,也不支持关系元算,只支持:++iter, iter++ 和 iter1 == iter2, iter1 != iter2 。
  16. 迭代器范围:左闭合区间
    [ first, last) : 表示范围从 first 开始,到 last 结束,但不包括 last。
    1).  当 first 与 last 相等时,迭代器范围为空;
    2).  当 first 与不相等时,迭代器范围内至少有一个元素,而且 first 指向该区间中的第一元素。此外,通过若干次自增运算可以使 first 的值不断增大,直到 first == last 为止。
  17. 容器定义的类型
    size_type 无符号整型,足以存储此容器类型的最大可能容器长度 
    iterator   此容器类型的迭代器类型
    const_iterator   元素的只读迭代器类型
    reverse_iterator   按逆序寻址元素的迭代器 
    const_reverse_iterator   元素的只读(不能写)逆序迭代器
    difference_type 足够存储两个迭代器差值的有符号整型,可为负数 
    value_type 元素类型 
    reference 元素的左值类型,是 value_type& 的同义词 
    const_reference 元素的常量左值类型,等效于 const value_type&
     
  18. 所有容器的迭代器支持的操作: begin  和  end  成员 
    c.begin() : 返回一个迭代器,它指向容器 c 的第一个元素
    c.end() : 返回一个迭代器,它指向容器 c 的最后一个元素的下一位置 
    c.rbegin() : 返回一个逆序迭代器,它指向容器 c 的最后一个元素 
    c.rend() : 返回一个逆序迭代器,它指向容器 c 的第一个元素前面的位置
  19. 容器元素都是副本
    在容器中添加元素时,系统是将元素值复制到容器里(所以要求元素的类型必须支持复制)。类似地,使用一段元素初始化新容器时,新容器存放的是原始元素的副本。被复制的原始值与新容器中的元素各不相关,此后,容器内元素值发生变化时,被复制的原值不会受到影响,反之亦然。 
  20. 如果用容器存副本,则容器销毁的时候,副本也会自动被删除。
    如果用容器存指针,则容器销毁的时候,不会删除这些指针所指向的对象,因此必须先手工删除完毕之后,再销毁容器。

  21. 顺序容器中添加元素
    c.push_back(t)  在容器 c 的尾部添加值为 t 的元素。返回 void 类型。 
    c.push_front(t)  在容器 c 的前端添加值为 t 的元素。返回 void 类型。只适用于 list 和 deque 容器类型。
    c.insert(p,t)  在迭代器 p 所指向的元素前面插入值为 t 的新元素。返回指向新添加元素的迭代器。
    c.insert(p,n,t) 在迭代器 p 所指向的元素前面插入 n 个值为 t 的新元素。返回 void 类型 。
    c.insert(p,b,e) 在迭代器 p 所指向的元素前面插入由迭代器 b 和 e 标记的范围内的元素。返回 void 类型。
  22. 添加元素可能会使迭代器失效
    任何 insert 或 push 操作都可能导致某些或所有迭代器失效。当编写循环将元素插入到 vector 或 deque 容器中时,程序必须确保迭代器在每次循环后都得到更新。
  23. 关系操作符
    所有的容器类型都支持用关系操作符来实现两个容器的比较。相比较的容器必须具有相同的容器类型,而且其元素类型也必须相同。
  24. 顺序容器的大小操作
    c.size()  返回容器 c 中的元素个数。返回类型为 c::size_type 
    c.max_size() 返回容器 c 可容纳的最多元素个数,返回类型为c::size_type
    c.empty()  返回标记容器大小是否为 0 的布尔值 
    c.resize(n) 调整容器 c 的长度大小,使其能容纳 n 个元素,如果 n < c.size(),则删除多出来的元素;否则,添加采用值初始化的新元素 
    c.resize(n,t) 调整容器 c 的长度大小,使其能容纳 n 个元素。所有新添加的元素值都为 t 
    resize 操作可能会使迭代器失效。在 vector 或 deque 容器上做 resize 操作有可能会使其所有的迭代器都失效。
  25. 访问顺序容器内元素的操作 
    c.back() 返回容器 c 的最后一个元素的引用。如果 c 为空,则该操作未定义
    c.front() 返回容器 c 的第一个元素的引用。如果 c 为空,则该操作未定义
    c[n] 返回下标为 n 的元素的引用 如果 n <0 或 n >= c.size(),则该操作未定义。只适用于 vector 和 deque 容器
    c.at(n) 返回下标为 n 的元素的引用。如果下标越界,则该操作未定义。只适用于 vector 和 deque 容器

     使用越界的下标,或调用空容器的 front 或 back 函数,都会导致程序出现严重的错误。

  26. 删除顺序容器内元素的操作 
    c.erase(p) 删除迭代器 p 所指向的元素返回一个迭代器,它指向被删除元素后面的元素。如果 p 指向容器内的最后一个元素,则返回的迭代器指向容器的超出末端的下一位置。如果 p 本身就是指向超出末端的下一位置的迭代器,则该函数未定义。
    c.erase(b,e) 删除迭代器 b 和 e 所标记的范围内所有的元素返回一个迭代器,它指向被删除元素段后面的元素。如果 e 本身就是指向超出末端的下一位置的迭代器,则返回的迭代器也指向容器的超出末端的下一位置。
    c.clear()  删除容器 c 内的所有元素。返回 void。
    c.pop_back() 删除容器 c 的最后一个元素。返回 void。如果 c 为空容器,则该函数未定义。
    c.pop_front() 删除容器 c 的第一个元素,返回 void。如果 c 为空容器,则该函数未定义。只适用于 list 或 deque 容器。
  27. 顺序容器的赋值操作 
    c1 = c2 删除容器 c1 的所有元素,然后将 c2 的元素复制给 c1。c1 和c2 的类型(包括容器类型和元素类型)必须相同。
    c1.swap(c2) 交换内容:调用完该函数后,c1 中存放的是 c2 原来的元素,c2 中存放的则是 c1 原来的元素。c1 和 c2 的类型必须相同。该函数的执行速度通常要比将 c2 复制到 c1 的操作快。
    c.assign(b,e) 重新设置 c 的元素:将迭代器 b 和 e 标记的范围内所有的元素复制到 c 中。b 和 e 必须不是指向 c 中元素的迭代器 。
    c.assign(n,t)  将容器 c 重新设置为存储 n 个值为 t 的元素。
  28. 选择容器的提示
    1).  如果程序要求随机访问元素,则应使用 vector 或 deque 容器。
    2).  如果程序必须在容器的中间位置插入或删除元素,则应采用 list 容器。 
    3).  如果程序不是在容器的中间位置,而是在容器首部或尾部插入或删除元素,则应采用 deque 容器。
    4).  如果只需在读取输入时在容器的中间位置插入元素,然后需要随机访问元素,则可考虑在输入时将元素读入到一个 list 容器,接着对此容器重新排序,使其适合顺序访问,然后将排序后的 list 容器复制到一个 vector 容器。
  29. string
    string类型可以视为字符容器。除了一些特殊操作,string 类型提供与 vector 容器相同的操作。string 类型与 vector 容器不同的是,它不支持以栈方式操纵容器:在 string 类型中不能使用 front、back 和 pop_back 操作。

    string 类型提供了容器类型不支持其他几种操作:
    •  substr 函数,返回当前 string 对象的子串。
    •  append 和 replace 函数,用于修改 string 对象。
    •  一系列 find 函数,用于查找 string 对象。

  30. string:substr 操作
    使用 substr 操作可在指定 string 对象中检索需要的子串。

    s.substr(pos, n) 返回一个 string 类型的字符串,它包含 s 中从下标 pos开始的 n 个字符
    s.substr(pos)  返回一个 string 类型的字符串,它包含从下标 pos 开始到s 末尾的所有字符 
    s.substr() 返回 s 的副本 
     
  31. append 和 replace
    s.append(args) 将 args 串接在 s 后面。返回 s 引用
    s.replace(pos, len, args)          删除 s 中从下标 pos 开始的 len 个字符,用 args 指定的字符替换之(在pos位置插入args)。返回 s 的引用 
    s.replace(b, e, args) 删除迭代器 b 和 e 标记范围内所有的字符,用 args 替换之(在pos位置插入args)。返回 s 的引用 
     
  32. string 类型的查找操作
    s.find( args)  在 s 中查找 args 的第一次出现 
    s.rfind( args) 在 s 中查找 args 的最后一次出现 
    s.find_first_of( args) 在 s 中查找 args 的任意字符的第一次出现
    s.find_last_of( args) 在 s 中查找 args 的任意字符的最后一次出现
    s.find_first_not_of( args) 在 s 中查找第一个不属于 args 的字符
    s.find_last_not_of( args) 在 s 中查找最后一个不属于 args 的字符
     

第10章 关联容器

  1. 关联容器支持通过来高效地查找和读取元素;顺序容器是通过元素在容器中的位置顺序存储和访问元素。
  2. map 的元素以键-值(key-value)对的形式组织:键用作元素在 map 中的索引,而值则表示所存储和读取的数据。
    set 仅包含一个键,并有效地支持关于某个键是否存在的查询。
    set适用于存储不同值的集合。map 容器则更适用于需要存储(乃至修改)每个键所关联的值的情况。

    map 关联数组,元素通过键来存储和读取
    set 大小可变的集合,支持通过键实现的快速读取
    multimap 支持同一个键多次出现的 map 类型
    multiset 支持同一个键多次出现的 set 类型 
     
  3. pair类型
    pair也是一种模板类型。

    pair<T1, T2> p1;  创建一个空的 pair 对象,它的两个元素分别是 T1 和 T2 类型,采用值初始化。
    pair<T1, T2> p1(v1, v2); 创建一个 pair 对象,它的两个元素分别是 T1 和 T2 ,其中 first 成员初始化为 v1,而 second 成员初始化为 v2。 
    make_pair(v1,v2); 以 v1 和 v2 值创建一个新 pair 对象,其元素类型分别是v1 和 v2 的类型。
    p1 < p2  两个 pair 对象之间的小于运算,其定义遵循字典次序:如果 p1.first < p2.first 或者 !(p2.first < p1.first) && p1.second < p2.second,则返回 true 。
    p1 == p2   如果两个 pair 对象的 first 和 second 成员依次相等,则这两个对象相等。该运算使用其元素的 == 操作符。
    p.first  返回 p 中名为 first 的(公有)数据成员。
    p.second 返回 p 的名为 second 的(公有)数据成员 。
     
  4. 关联容器不提供front、push_front、pop_front、back、push_back以及pop_back操作;
  5. 要使用map对象,则必须包含map头文件;
    定义map对象时,必须分别指明键和值的类型。map<string, int> word_count;

    map<k, v> m;                     创建一个名为 m 的空 map 对象,其键和值的类型分别为 k 和 v
    map<k, v> m(m2);  创建 m2 的副本 m,m 与 m2 必须有相同的键类型和值类型 
    map<k, v> m(b, e);  创建 map 类型的对象 m,存储迭代器 b 和 e 标记的范围内所有元素的副本。元素的类型必须能转换为 pair<const k, v> 
     
  6. 关联容器的键类型必须支持 < 操作符,而且该操作符应能“正确地工作”;
  7. map 定义的类型
    map<K, V>::key_type                    在 map 容器中,用做索引的键的类型 
    map<K,V>::mapped_type 在 map 容器中,键所关联的值的类型 
    map<K,V>::value_type 一个 pair 类型,它的 first 元素具有 const map<K, V>::key_type 类型,而 second 元素则为 map<K, V>::mapped_type 类型 
    谨记: value_type 是 pair 类型,它的值成员可以修改,但键成员不能修改。 
  8. 给 map 添加元素
    (1) 使用insert 成员实现;
    (2) 先用下标操作符获取元素,然后给获取的元素赋值。
  9. 使用下标访问 map 对象
    使用下标[i]访问map中不存在的元素将导致在map容器中添加一个新的元素,它的键即为该下标值;
  10. map::insert 的使用 
    m.insert(e) e 是一个用在 m 上的 value_type 类型的值。如果键(e.first)不在 m 中,则插入一个值为 e.second 的新元素;如果该键在 m 中已存在,则保持 m 不变。该函数返回一个 pair 类型对象,包含指向键为 e.first 的元素的 map 迭代器,以及一个 bool 类型的对象,表示是否插入了该元素。
    m.insert(beg, end)                                                                        beg 和 end 是标记元素范围的迭代器,其中的元素必须为 m.value_type 类型的键-值对。对于该范围内的所有元素,如果它的键在 m 中不存在,则将该键及其关联的值插入到 m。返回 void 类型 。
    m.insert(iter,e)  e 是一个用在 m 上的 value_type 类型的值。如果键(e.first)不在 m 中,则创建新元素,并以迭代器 iter 为起点搜索新元素存储的位置。返回一个迭代器,指向 m 中具有给定键的元素。
     
  11. 查找并读取 map 中的元素
    不修改 map 对象的查询操作:

    m.count(k)  返回 m 中 k 的出现次数
    m.find(k) 如果 m 容器中存在按 k 索引的元素,则返回指向该元素的迭代器。如果不存在,则返回超出末端迭代器。
     
  12. 从map中删除元素
    m.erase(k)   删除 m 中键为 k 的元素。返回 size_type 类型的值,表示删除的元素个数 
    m.erase(p)  从 m 中删除迭代器 p 所指向的元素。p 必须指向 m 中确实存在的元素,而且不能等于 m.end()。返回 void 
    m.erase(b, e)                                                 从 m 中删除一段范围内的元素,该范围由迭代器对 b 和 e 标记。b 和 e 必须标记 m 中的一段有效范围:即 b 和 e 都必须指向 m 中的元素或最后一个元素的下一个位置。而且,b 和 e 要么相等(此时删除的范围为空),要么 b 所指向的元素必须出现在 e 所指向的元素之前。返回 void 类型 
  13. map 对象的迭代遍历
    与其他容器一样,map 同样提供 begin 和 end 运算,以生成用于遍历整个容器的迭代器。例如,可如下将 map 容器 word_count 的内容输出:
    map<string, int>::const_iterator  map_it = word_count.begin();
    while (map_it != word_count.end())
     {
             cout << map_it->first << " occurs "  << map_it->second << " times" << endl;
             ++map_it;

    在使用迭代器遍历map 容器时,迭代器指向的元素按键的升序排列。
  14. set
    map 容器是键-值对的集合,set 容器只是单纯的键的集合。
    两种例外包括:set 不支持下标操作符,而且没有定义 mapped_type 类型。
    在 set 容器中,value_type 不是 pair 类型,而是与 key_type 相同的类型。它们指的都是 set 中存储的元素类型。与 map 一样,set 容器存储的键也必须唯一,而且不能修改。

  15. multimap 允许一个键对应多个实例。
    multimap不支持下标运算,因为某个键可能对应多个值;
  16. multimap添加元素
    由于键不要求是唯一的,因此每次调用 insert 总会添加一个元素。
  17. multimap 删除元素 
    带有一个键参数的 erase 版本将删除拥有该键的所有元素,并返回删除元素的个数。
  18. 在 multimap 和 multiset 中查找元素
    关联容器 map 和 set 的元素是按顺序存储的。
    在 multimap 中,同一个键所关联的元素必然相邻存放。

    方法一:使用 find 和 count 操作
    count 函数求出某键出现的次数,而 find 操作则返回一个迭代器,指向第一个拥有正在查找的键的实例:
    string search_item("Alain de Botton");
    typedef multimap<string, string>::size_type sz_type;
    sz_type entries = authors.count(search_item);
    multimap<string,string>::iterator iter = authors.find(search_item);
    for (sz_type cnt = 0; cnt != entries; ++cnt, ++iter)
        cout << iter->second << endl; // print each title 
    首先,调用 count 确定某作者所写的书籍数目,然后调用 find 获得指向第一个该键所关联的元素的迭代器。for 循环迭代的次数依赖于 count 返回的值。在特殊情况下,如果 count 返回 0 值,则该循环永不执行。

    方法二:与众不同的面向迭代器的解决方案 
    更优雅简洁的方法是使用两个未曾见过的关联容器的操作:lower_bound 和 upper_bound。

    m.lower_bound(k) 返回一个迭代器,指向键不小于 k 的第一个元素 
    m.upper_bound(k)  返回一个迭代器,指向键大于 k 的第一个元素 
    m.equal_range(k)   返回一个迭代器的 pair 对象 它的 first 成员等价于 m.lower_bound(k)。而 second 成员则等价于 m.upper_bound(k) 
    typedef multimap<string, string>::iterator authors_it;
    authors_it beg = authors.lower_bound(search_item),  end = authors.upper_bound(search_item);
    while (beg != end)

         cout << beg->second << endl; // print each title
         ++beg;
     

第11章 泛型算法
     
     每个泛型算法的实现都独立于单独的容器,并且不依赖于容器存储的元素类型。
     泛型算法需要使用迭代器,迭代器有如下要求:
        •  支持自增操作:从一个元素定位下一个元素
          •  提供解引用:访问元素的值
          •  支持相等和不等操作符:用于判断2个迭代器是否相等 
 
     “普通”的迭代器不修改基础容器的大小。算法可能会改变存储在容器中的元素的值,也许会在容器内移动元素,但是,算法从不直接添加或删除元素。 
  1. 头文件
    使用泛型算法必须包含 algorithm 头文件:
    #include <algorithm>
    标准库还定义了一组泛化的算术算法(generalized numeric algorithm),使用这些算法则必须包含 numeric 头文件:
    #include <numeric>
  2. 只读算法
    (1) find

    vector<int> vec;
    ...

    int search_value = 42;
    vector<int>::const_iterator result = find(vec.begin(), vec.end(), search_value); 
    内置数组也可以使用迭代器和find实现查找
    int ia[6] = {27, 210, 12, 47, 109, 83};
    int search_value = 83;
    int *result = find(ia, ia + 6, search_value);

    (2) count
    count在容器中查找某个值出现的次数

    int cnt = count(vec.begin(), vec.end(), search_value);

    (2) accumulate
    int sum = accumulate(vec.begin(), vec.end(), 42);//将 sum 设置为 vec 的元素之和再加上 42

    (3) find_first_of
    该算法带有2段迭代器范围,在第一段范围内查找与第二段范围内任意元素匹配的元素,找到了返回第一个匹配的元素 迭代器,否则就返回第一段范围的end迭代器。

  3. 写入容器的算法
    (1) fill
    fill(vec.begin(), vec.end(), 0); // reset each element to 0

    (2) fill_n 和 back_inserter
    vector<int> vec; // empty vector
    // ok: back_inserter creates an insert iterator that adds elements to vec
    fill_n (back_inserter(vec), 10, 0); // appends 10 elements to vec

  4. 写入到目标迭代器的算法
    (1) copy
    vector<int> ivec; // empty vector
    // copy elements from ilst into ivec
    copy (ilst.begin(), ilst.end(), back_inserter(ivec));
    //copy 从输入范围中读取元素,然后将它们复制给目标 ivec。更好的方法如下:
    // better way to copy elements from ilst
    vector<int> ivec(ilst.begin(), ilst.end()); //直接初始化

    (2) replace
    //这个调用将所有值为 0 的实例替换成 42
    replace(ilst.begin(), ilst.end(), 0, 42);

    (3) replace_copy vector<int> ivec;
    replace_copy (ilst.begin(), ilst.end(),back_inserter(ivec), 0, 42);
    //调用该函数后,ilst 没有改变,ivec 存储 ilst 一份副本,而 ilst 内所有的 0 在 ivec 中都变成了 42

  5. 对容器元素重新排序的算法
    (1) sort-排序
    sort(words.begin(), words.end());//调用 sort 后,此 vector 对象的元素按次序排列

    (2) unique-删除重复元素
    vector<string>::iterator end_unique = unique(words.begin(), words.end()); 
    //该算法删除相邻的重复元素,然后重新排列输入范围内的元素,并且返回一个迭代器,表示无重复的值范围的结束。

    (3) erase-清空指定范围内的元素
    words.erase(end_unique, words.end());

  6. 插入迭代器
    •  back_inserter,创建使用 push_back 实现插入的迭代器。
    •  front_inserter,使用 push_front 实现插入。
    •  inserter,使用 insert 实现插入操作。除了所关联的容器外,inserter 还带有第二实参:指向插入起始位置的迭代器。
  7. iostream 迭代器 
    istream_iterator 用于读取输入流,而 ostream_iterator 则用于写输出流
    istream_iterator<int> in_iter(cin); // read ints from cin
    istream_iterator<int> eof;      // istream "end" iterator
    vector<int> vec(in_iter, eof);  // construct vec from an iterator range
  8. 反向迭代器
    rbegin 和 rend
    vector<int>::reverse_iterator r_iter;
    for (r_iter = vec.rbegin(); // binds r_iter to last element
         r_iter != vec.rend();  // rend refers 1 before 1st element
         ++r_iter)              // decrements iterator one element
    cout << *r_iter << endl;    // prints 9,8,7,...0

    以降序排列 vector,只需向 sort传递一对反向迭代器:
    // 按升序排序
    sort(vec.begin(), vec.end());
    // 按降序排序
    sort(vec.rbegin(), vec.rend());

  9. const 迭代器

C++ Primer(第4版)-学习笔记-第2部分:容器和算法的更多相关文章

  1. C++Primer第5版学习笔记(四)

    C++Primer第5版学习笔记(四) 第六章的重难点内容         你可以点击这里回顾第四/五章的内容       第六章是和函数有关的知识,函数就是命名了的代码块,可以处理不同的情况,本章内 ...

  2. C++Primer第5版学习笔记(三)

    C++Primer第5版学习笔记(三) 第四/五章的重难点内容           你可以点击这里回顾第三章内容       因为第五章的内容比较少,因此和第四章的笔记内容合并.       第四章是 ...

  3. C++Primer第5版学习笔记(二)

    C++Primer第5版学习笔记(二) 第三章的重难点内容         这篇笔记记录了我在学习C++常用基本语法的学习过程,基本只记录一些重难点,对概念的描述不是一开始就详尽和准确的,而是层层深入 ...

  4. C++Primer第5版学习笔记(一)

    C++Primer第5版学习笔记(一) 第一.二章的重难点内容        这个笔记本主要记录了我在学习C++Primer(第5版,中文版)的过程中遇到的重难点及其分析.因为第一.二章都比较简单,因 ...

  5. C++Primer第五版学习笔记

    <C++ Primer>Learning Note 程序实例下载地址:http://www.informit.com/title/0321714113 第一章            开始 ...

  6. C++ Primer(第4版)-学习笔记-第5部分:高级主题

    第17章  用于大型程序的工具 异常处理 不存在数组或函数类型的异常.相反,如果抛出一个数组,被抛出的对象转换为指向数组首元素的指针,类似地,如果抛出一个函数,函数被转换为指向该函数的指针. 不要抛出 ...

  7. C++ Primer(第4版)-学习笔记-第4部分:面向对象编程与泛型编程

    第15章 面向对象编程OOP(Object-oriented programming)           面向对象编程基于三个基本概念:数据抽象.继承和动态绑定.      在 C++ 中,用类进行 ...

  8. C++ Primer(第4版)-学习笔记-第3部分:类和数据抽象

    第12章 类       每个类可以没有成员,也可以定义多个成员,成员可以是数据.函数或类型别名. 成员函数必须在类内部声明,可以在类内部定义,也可以在类外部定义.如果在类内部定义,就默认是内联函数. ...

  9. C++ Primer(第4版)-学习笔记-第1部分:基本语言

    第1章  快速入门 每个C++程序都包含一个或多个函数,而且必须有一个命名为main. main函数是唯一被操作系统显式调用的函数,main函数的返回值必须是int或者void(无返回值) 函数体是函 ...

随机推荐

  1. UVA 12697 Minimal Subarray Length

    Minimal Subarray Length Time Limit: 3000ms Memory Limit: 131072KB This problem will be judged on UVA ...

  2. Convolutions in TensorFlow

    Convolutions in TensorFlow Convolutions without training You might already be familiar with the term ...

  3. Uva12657 Boxes in a Line

    题目链接:传送门 分析:每次操作都会花费大量时间,显然我们只需要关注每个元素的左边是啥,右边是啥就够了,那么用双向链表,l[i]表示i左边的数,r[i]表示i右边的数,每次操作模拟一下数组的变化就好了 ...

  4. android安卓程序源码---高仿微信源码

    先截几张图: 部份源代码如下所示: package cn.buaa.myweixin; import java.util.ArrayList; import android.os.Bundle; im ...

  5. 8、Java并发性和多线程-静态条件与临界区

    以下内容转自http://ifeve.com/race-conditions-and-critical-sections/: 在同一程序中运行多个线程本身不会导致问题,问题在于多个线程访问了相同的资源 ...

  6. git 手动操作

    git 手动操作 以下所有的情况都需要在上面那个目录下: 查看改动: git status // 所有改动都在这里. 提交代码: git add <file_name> // 把代码放到 ...

  7. ZOJ 3201

    id=15737" target="_blank">Tree of Tree Time Limit: 1000MS   Memory Limit: 32768KB ...

  8. 使用JSONObject 深度序列化和反序列化

    JSONObject 和JSONArray 是json-lib.jar里面最经常使用的两个类,分别能够对对象和数组(集合)进行序列化和反序列化,结构清晰命了,简单易用,功能强大,效率比較高,使用至今一 ...

  9. 3.5 在批处理模式下使用mysql

    在前面的章节中,你交互式地使用mysql输入查询而且查看结果.你也能够以批模式执行mysql.为了做到这些.把你想要执行的命令放在一个文件里,然后告诉mysql从文件读取它的输入: shell> ...

  10. php訪问控制

    訪问控制通过keywordpublic,protected和private来实现. 被定义为公有的类成员能够在不论什么地方被訪问.被定义为受保护的类成员则能够被其自身以及其子类和父类訪问.被定义为私有 ...