第09章_顺序容器

顺序容器概述

  • 顺序容器为程序员提供了控制元素存储和访问顺序的能力
  • vector, deque, list, forward_list, array, string

容器类概览

迭代器

容器类型成员

begin 和 end 成员

  • begin 指向容器中第一个元素
  • end 指向容器中尾元素之后位置

容器定义和初始化

赋值和 swap

  • 赋值运算符要求左边和右边的运算对象具有相同的类型, 它将右边运算对象中所有的元素拷贝到左边运算对象中
  • 顺序容器(array 除外)还定义了一个名为 assign 的成员, 允许从一个不同但相容的类型赋值, 或者从容器的一个子序列赋值
  • 除 array 外, swap 部队任何元素进行拷贝, 删除或插入操作. 可以保证在常数时间内完成

容器大小操作

关系运算符

  • 每个容器类型都支持相等运算符(== 和 !=); 除了无序关联容器外所有容器都支持关系运算符(>, >=, <, <=)
  • 关系运算符左右两边的运算对象必须是相同类型的容器, 且必须保存相同类型的元素
  • 只有当其元素类型也定义了相应的比较运算符时, 才可以使用关系运算符来比较两个容器
  • 容器的相等运算符实际上是使用元素的 == 运算符实现比较的, 而其他关系运算符是使用元素的 < 运算符. 如果元素类型不支持所需运算符, 那么保存这种元素的容器就不能使用相应的关系运算

顺序容器操作

向顺序容器添加元素

  • 当调用一个 emplace 成员函数时, 是将参数传递给元素类型的构造函数. emplace 成员使用这些参数在容器管理的内存空间中直接构造元素(push_back, insert 等是拷贝元素)

访问元素

  • 每个顺序容器都有一个 front 成员函数, 而除了 forward_list 之外的所有顺序容器都有一个 back 成员函数(要确保非空)
  • 在容器中访问元素的成员函数(front, back, 下标和 at)返回的都是引用; 如果容器是一个 const 对象, 则返回值是 const 的引用

删除元素

特殊的 forward_list 操作

改变容器大小

  • resize: 若当前大小大于所要求的大小, 容器后部的元素会被删除; 若当前大小小于新大小, 会将新元素添加到容器后部

容器操作可能使迭代器失效

  • 向容器添加元素和从容器中删除元素的操作可能会使指向容器元素的指针, 引用或迭代器失效

vector 对象是如何增长的

额外的 string 操作

构造 string 的其他方法

  • 当从一个 const char* 创建 string 时, 指针指向的数组必须以空字符结尾, 拷贝操作遇到空字符时停止; 若还传递给构造函数一个计数值, 数组就不必以空字符结尾.
  • substr 操作返回一个 string, 是原始 string 的一部分或全部的拷贝

改变 string 的其他方法

string 搜索操作

  • find 函数完成最简单的搜索, 查找参数制定的字符串, 若找到, 则返回第一个匹配位置的下标, 否则返回 npos

compare 函数

数值转换

  • to_string(val)
  • stoi, stol, stof, stod…

容器适配器

  • 三种顺序容器适配器: stack, queue, priority_queue
  • 一个容器适配器接受一种已有的容器类型, 使其行为看起来像一种不同的类型
  • 每个适配器都定义两个构造函数: 默认构造函数创建一个空对象, 接受一个容器的构造函数拷贝该容器来初始化适配器
    1
    2
    std::deque<int> deq;
    std::stack<int> stk(deq); // 从 deq 拷贝元素到 stk
  • 默认情况下, stack 和 queue 是基于 deque 实现的, priority_queue 是在 vector 之上实现的
  • 可以在创建一个适配器时将一个命名的顺序容器作为第二个类型参数, 来重载默认容器类型
    1
    std::stack<std::string, std::vector<std::string>> str_stk; // 在 vector 上实现的空栈
  • 每个容器适配器都基于底层容器类型的操作定义了自己的特殊操作, 我们只可以使用适配器操作, 而不能使用底层容器类型的操作