第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. nginx+keepalived+consul 实现高可用集群

    继 负载均衡 之 nginx+consul+consul template,我这次将使用2台虚拟机,来做一个简单的双机负载均衡试验. 试验目标: 1. 当参加负载均衡的子节点服务,有任何其中一个或多个 ...

  2. 数据库中间件MyCat学习总结(1)——MyCat入门简介

    为什么需要MyCat? 虽然云计算时代,传统数据库存在着先天性的弊端,但是NoSQL数据库又无法将其替代.如果传统数据易于扩展,可切分,就可以避免单机(单库)的性能缺陷. MyCat的目标就是:低成本 ...

  3. 转载 - Struts2基于XML配置方式实现对action的所有方法进行输入校验

    出处:http://www.cnblogs.com/Laupaul/archive/2012/03/15/2398360.html http://www.blogjava.net/focusJ/arc ...

  4. 【转】建立一个更高级别的查询 API:正确使用Django ORM 的方式

    这个就比较深入啦... http://www.oschina.net/translate/higher-level-query-api-django-orm 结论: 在视图和其他高级应用中使用源生的O ...

  5. MySQL大小写问题的简单说明(关键字/函数/表名)(转)

    MySQL语句中字母大小写规则随着语句元素的不同而变化,同时还要取决于MySQL服务器主机上的操作系统. SQL关键字与函数名 关键字和函数名不区分字母的大小写.如.abs.bin.now.versi ...

  6. DATASNAP压缩过滤器的使用

    ZLIBCOMPRESSION FILTER 作为范例,我们使用已随D2010提供的DataSnap过滤器.可用于在客户端和服务端压缩数据流.这里说的ZlibCompression过滤器可以在DbxC ...

  7. curl -O 下载文件

    curl -O 下载文件 学习了:http://blog.csdn.net/wulong710/article/details/53127606 curl -O http://a.b.c/a.tar ...

  8. 如何使用VB编写Excel的COM组件

    1 新建工程中选择"外接程序",点击打开之后右侧的属性窗口即显示为MyAddIn工程.(注意如果你使用的是VB精简版的没有"外接程序"的选项,请下载完整版的) ...

  9. H5端调起百度地图、腾讯地图app

    来自一个需求的总结: 在微信公众号中根据地图上的marker和label,或者搜索结果点击调起地图APP进行导航. 一开始是使用百度地图进行开发,后面转腾讯是因为微信不允许不是自家或者合作方的APP在 ...

  10. LeetCode 290. Word Pattern (词语模式)

    Given a pattern and a string str, find if str follows the same pattern. Here follow means a full mat ...