[C++ Primer] 字符串、向量和数组
标准库类型 string
-
标准库类型
string
表示可变长的字符序列,使用该类型需包含string头文件。作为标准库的i一部分,string定义在命名空间
std
中。 -
拷贝初始化:使用等号(=)初始化一个变量
直接初始化:不使用等号
string s5 = "hiya"; // 拷贝初始化 string s6("hiya"); // 直接初始化 string s7(10,'c'); // 直接初始化
-
getline()
函数
参数:输入流,string对象
功能:函数从给定的输入流中读入内容,直到遇到换行符为止(换行符也被读进来了),然后把所读的内容存到string对象中(不存换行符,丢弃)
-
因为某些历史原因,也为了与C兼容,所以C++语言中的字符串字面值并不是标准库类型string的对象。字符串字面值与string是不同的类型。
-
范围for语句
遍历给定序列中的每个元素并对序列中的每个值执行某种操作,其语法形式是:
for (declaration : expression) statement
其中,
expression
部分是一个对象,用于表示一个序列。declaration
部分负责定义一个变量,该变量将被用于访问序列中的基础元素。每次迭代,declaration部分的变量会被初始化为expression部分的下一个元素值。
标准库类型 vector
- 标准库类型
vector
表示对象的集合,其中所有对象的类型相同。集合中每个对象都有一个与之对应的索引,索引用于访问对象。
编译器根据模板创建类或函数的过程称为实例化(instantiaton)。 - 范围for语句体内不应改变其所遍历序列的大小。
- vector对象(以及string对象)的下标运算符可用于访问已存在的元素,不能用于添加元素。
迭代器介绍
数组
-
数组是一种复合类型,数组中元素的个数也属于数组类型的一部分,编译时维度应该已知。
-
复杂的数组声明
int *ptrs[10]; // ptrs是含有10个整型指针的数组 int &refs[10] = /*?*/; // 错误,不存在引用的数组 int (*Parray)[10] = &arr; // Parray指向一个含有10个整数的数组 int (&arrRef)[10] = arr; // arrRef引用一个含有10个整数的数组 int *(&array)[10] = ptrs; // array是数组的引用,该数组含有10个int型指针
要想理解数组声明的含义,最好的方法是从数组的名字开始按照从内到外的顺序阅读。
-
使用数组下标时,通常将其定义为
size_t
类型。size_t是一种机器相关的无符号类型。 -
在很多用到数组名字的地方,编译器都会自动地将其转换为一个指向数组首元素的指针:
string nums[] = {"one","two","three"}; string *p2 = nums; // 等价于p2 = &nums[0];
当使用数组作为一个auto变量的初始值时,推断得到的类型是指针而非数组:
int ia[] = {0,1,2,3,4,5,6,7,8,9}; auto ia2(ia); // ia2是一个整型指针,指向ia第一个元素
当使用
decltype
关键字时上述转换不会发生,decltype(ia)
返回的类型是由10个整数构成的数组:decltype(ia) ia3 = {0,1,2,3,4,5,6,7,8,9}; ia3[4] = i; // 正确:把i的值赋给ia3的一个元素
-
标准库函数begin和end
这两个函数与容器中的两个同名成员函数功能类似,不过数组毕竟不是类类型,因此这两个函数不是成员函数。正确使用形式是将数组作为它们的参数:
int ia = {0,1,2,3,4,5,6,7,8,9}; int *beg = begin(ia); // 指向ia首元素的指针 int *last = end(ia); // 指向ia尾元素的下一位置的指针
-
两个指针相减的结果的类型是一种名为
ptrdiff_t
的标准库类型,因为差值可能为负值,所以ptrdiff_t是一种带符号类型。 -
C风格字符串
C风格字符串不是一种类型,而是为了表达和使用字符串而形成的一种约定而成的写法。按此习惯书写的字符串存放在字符数组中并以空字符结束,即在字符串最后一个字符后面跟着一个空字符('\0')。一般利用指针来操作这些字符串。
strlen(p) strcmp(p1,p2) strcat(p1,p2) strcpy(p1,p2)
传入此类函数的指针必须指向以空字符作为结束的数组:
char ca[] = {'C','+','+'}; // 不以空字符结束 cout << strlen(ca) << endl; // 严重错误:ca没有以空字符结束
-
不能用string对象直接初始化指向字符的指针,需使用string的c_str成员函数:
string s("Hello World!"); char *str = s; // 错误:不能用string对象初始化char* const char *str = s.c_str(); // 正确
c_str
函数的返回值是一个C风格的字符串。即函数的返回结果是一个指针,该指针指向一个以空字符结束的字符数组,这个数组所存的数据恰好与那个string对象一样。 -
现代的C++程序应当尽量使用vector和迭代器,避免使用内置数组和指针;尽量使用string,避免使用C风格的基于数组的字符串。
多维数组
-
要使用范围for语句处理多维数组,除了最内层的循环外,其他所有循环的控制变量都应该是引用类型。
int ia[3][4]; for(auto row : ia) // 错误 for(auto col : row) // row不是引用类型,编译器初始化row时会自动将其转换为指向该数组内首元素的指针