标准库类型 string
string 对象与字面值相加,必须确保每个加法运算符(+)的两侧至少有一个是 string 。
string s1 = "hello";
string s2 = s1 + "," + "world"; // 错误,不能把字面值直接相加
处理 string 对象的每个字符
string str("some string");
for (auto c : str) // 范围 for 语句
cout << c << endl;
标准库类型 vector
vector 表示对象的集合,其中所有对象的类型都相同,因为引用不是对象,所以不存在包含引用的 vector。
初始化
vector<int> v1{10}; // 花括号为列表初始化,v1 有 1 个元素,该元素的值为 10
vector<int> v2(10); // 圆括号为值初始化,可以理解为构造,v2 有 10 个元素,每个的值都为 0
vector<int> v3{10, 1}; // v3 有 2 个元素,值分别为 10 和 1
vector<int> v4(10, 1); // v4 有 10 个元素,每个元素都为 0
// 列表初始化时,花括号里的值必须与元素类型相同
// 花括号可以代替圆括号,但圆括号无法代替花括号
vector<string> v5("hi"); // 错误
vector<string> v6{10}; // 正确,无法执行列表初始化时,编译器会尝试用值初始化
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 个指针