title: 第三章——字符串、向量和数组
date: 2022-04-30 15:42:23
tags:
- C++ Primer
mathjax: true
第三章——字符串、向量和数组
两种重要的标准库类型:string 和 vector。string 表示可变长的字符序列,vector 存放的是某种给定类型对象的可变长序列。
内置数组类型,和其他内置类型一样,数组的实现与硬件密切相关。因此比较于标准库类型 string 和 vector,数组在灵活性上稍显不足。
1. 命名空间的 using 声明
- 头文件不应该包含 using 声明
标准库类型 String
// --------
string::size_type // string 类成员 size()的返回值类型,也是 string 的下标类型。
// --------
-
定义和初始化 string 对象
string s1; //默认初始化,s1 是一个空串 string s2(s1); //s2 是 s1 的副本 string s3("value"); //s3是字面值"value"的副本,除了字面值最后的那个空字符外 string s3 = "value"; //s3是字面值"value",s3是字面值"value"的副本 string s4(n, 'c'); //把 s4 初始化为由连续 n 个字符 c 组成的串
-
拷贝初始化 和 直接初始化
-
切记,因为某些历史原因,也为了与C兼容,所以C++ 语言中的字符串字面值并不是标准库类型 string 的对象。
字符串字面值与 string 是不同的类型。
-
使用基于范围的 for 语句
-
无论何时用到字符串的下标,都应该注意检测其合法性。
标准库类型 vector
// -------
vector<int>::size_type // vector<int> 对象的成员 size() 的返回值类型,同样也是 vector<int>下标类型
// ------
-
定义和初始化 vector 对象
vector<T> v1 // v1是一个空 vector, 它潜在的元素是T类型的,执行默认初始化 vector<T> v2(v1) // v2中包含有 v1 所有元素的副本 vector<T> v2 = v1 // 等价于 v2(v1),v2中包含有 v1 所有元素的副本 vector<T> v3(n, val) //v3包含了n个重复的元素,每个元素的值都是val vector<T> v4(n) //v4包含了n个重复地执行了值初始化地对象 vector<T> v5{a,b,c...} //v5包含了初始值个数地元素,每个元素被赋予相应地初始值 vector<T> v5 = {a,b,c...}//等价于v5{a,b,c...}
-
vector 对象(以及 string 对象)的下标运算符可用于访问已存在的元素,而不能用于添加元素。
-
确保下标合法的一种有效手段就是尽可能使用范围 for 语句。
迭代器
-
vector 支持下标运算符,这点和 string 一样; string 支持迭代器,这也和 vector 是一样的。
-
类似于指针类型,迭代器也提供了对对象的间接访问。
-
有效的迭代器或者指向某个元素,或者指向容器中尾元素。
// ----- difference_type // 两迭代器相减得到距离的数据类型,带符号的整型数。 // -----
谨记,但凡使用了迭代器的循环体,都不要向迭代器所属的容器添加元素。
数组
// ------
size_t // 位于头文件cstddef中 ,数组下标的数据类型 , 是一种机器相关的无符号类型。
// ------
-
要想理解数组声明的含义,最好的办法是从数组的名字开始按照由内向外的顺序阅读。
int ia[] = {0,1,2,3,4,5}; // ia 是一个含有10个整数的数组 int *beg = begin(ia); // 指向 ia 首元素的指针 int *last = end(ia); // 指向 arr 尾元素的下一位置的指针 // --------- begin() // 函数,用于计算数组首元素的指针, 定义在 iterator 头文件中 end() // 函数,用于计算数组尾元素下一位置的指针 // ---------
// 两指针相减的数据类型 constexpr size_t sz = 5; int arr[sz] = {1,2,3,4,5}; auto n = end(arr) - begin(arr); // 两指针相减的结果的类型是一种名为 ptrdiff_t 的标准库类型,和 size_t 一样也是一种定义在 cstddef头文件中的机器相关类型 // ------- ptrdiff_t // 位于cstddef中,begin()函数返回值的数据类型, // -------
-
标准库类型 string 和 vector 也能执行下标运算,但是数组与它们相比还是有所不同。标准库类型限定使用的下标必须是无符号类型,而内置的下标运算无此要求,上面的最后一个例子很好地说明了这一点。
-
尽管 C++ 支持 C 风格字符串,但是 C++ 程序中最好还是不要使用它们。
-
C风格的字符串,不是一种类型,而是为了表达和使用字符串而形成的一种约定俗成的写法。按照此习惯书写的字符串存放在字符数组中并以空字符串结束(字符串后面跟一个空字符’\0’)。一般用指针来操作这些字符串。
-
对大多数应用来说,使用标准库 string 要比使用 C 风格字符串更安全,更高效。
-
现代的 C++ 程序当尽量使用 vector 和迭代器,避免使用内置数组和指针;应尽量使用 string ,避免使用 C 风格的基于数组的字符串。
-
严格来说,C++ 语言中没有多维数组,通常所说的多维数组其实是数组的数组。
-
数组初始化局部元素,其他元素默认初始化为 0 。
-
要使用范围 for 语句处理多维数组,除了最内层的循环外,其他所有循环的控制变量都应该是引用类型。
-
数组和指向数组元素的指针在一个较低层次上实现了与标准库类型 string 和 vector 类似的功能。一般来说,应该优先选用标准库提供的类型,之后在考虑 C++ 语言内置的低层替代品数组或指针。
类型别名声明,新标准
using int_array = int[4]; // 新标准下类型别名的声明 typedef int int_array[4]; // 等价的 typedef 声明