标准库类型 string

string 对象与字面值相加,必须确保每个加法运算符(+)的两侧至少有一个是 string 。

  1. string s1 = "hello";
  2. string s2 = s1 + "," + "world"; // 错误,不能把字面值直接相加

处理 string 对象的每个字符

  1. string str("some string");
  2. for (auto c : str) // 范围 for 语句
  3. cout << c << endl;

标准库类型 vector

vector 表示对象的集合,其中所有对象的类型都相同,因为引用不是对象,所以不存在包含引用的 vector。

初始化

  1. vector<int> v1{10}; // 花括号为列表初始化,v1 有 1 个元素,该元素的值为 10
  2. vector<int> v2(10); // 圆括号为值初始化,可以理解为构造,v2 有 10 个元素,每个的值都为 0
  3. vector<int> v3{10, 1}; // v3 有 2 个元素,值分别为 10 和 1
  4. vector<int> v4(10, 1); // v4 有 10 个元素,每个元素都为 0
  5. // 列表初始化时,花括号里的值必须与元素类型相同
  6. // 花括号可以代替圆括号,但圆括号无法代替花括号
  7. vector<string> v5("hi"); // 错误
  8. vector<string> v6{10}; // 正确,无法执行列表初始化时,编译器会尝试用值初始化
  9. vector<string> v7{10, "hi"}; // 正确,v7 含有 10 个元素 "hi"

vector 对象的类型总是包含着元素的类型

vector<int>::size_type;  // 正确
vector::size_type;  // 错误

注:

  • 最好创建空的 vector 对象,在运行时使用 push_back 动态添加元素,而不要在定义 vector 时设定其大小。
  • 如果循环体内部含有向 vector 添加元素的语句,则不能使用范围 for 循环

    迭代器介绍

    所有标准库容器都可以使用迭代器,若容器为空,则 begin 和 end 返回的是同一个迭代器。

标准容器迭代器的运算符

*iter 返回迭代器 iter 所指元素的引用
iter -> mem 解引用 iter 并获取该元素的名为 mem 的成员,等价于 (*iter).mem
++iter 令 iter 指向下一个元素
—iter 令 iter 指向上一个元素
iter == iter
iter != iter
判断两个迭代器是否指向同一元素,或者它们是同一个容器的尾后迭代器。
iter 不使用大于小于号(< >)用作条件判定。

若只需要读操作,最好用 cbegin 与 cend

auto it = v.cbegin();  // it 类型为 vector<int>::const_iterator

改变 vector 对象容量的操作,比如 push_back,会使迭代器失效。

数组

数组的维度必须是一个常量表达式。(即 const、constexpr 或字面值)

字符数组可用字符串字面值初始化

char c[] = "c++";

在大多数表达式中,使用数组类型的对象其实是使用一个指向该数组首元素的指针

int ia[] = {1, 2, 3, 4, 5};
auto ia2(ia);  // ia2 是一个整型指针,指向 ia 的第一个元素
auto ia2(&ia[0]); // 编译器实际执行过程,ia2 显然是 int*

不能将数组的内容拷贝给其他数组作为初始值,也不能用数组为其他数组赋值

int a[] = {0, 1, 2};
int a[] = a;  // 错误
a2 = a;  // 错误

向理解数组声明的含义,最好的办法是从数组的名字开始,按照由内向外的顺序阅读。

int *ptrs[10];  // ptrs 是含有 10 个整型指针的数组
int &refs[10] = /*?*/;  // 错误,不存在引用的数组
int (*Parray)[10] = &arr;  // Parray 指向一个含有 10 个整数的数组
int (&arrRef)[10] = arr;  // arrRef 引用一个含有10个整数的数组
int *(&arry)[10] = ptrs;  // arry 是数组的引用,该数组含有 10 个指针