3.1 命名空间的using声明
1、以命名空间std为例,两种声明方式:
(1)using std::cin;(或cout,endl等)
(2)using namespace std;
2、头文件中不应包含using声明。
3.2 标准库类型string
3.2.1 定义和初始化string对象
1、初始化的方式分为拷贝初始化(使用等号)与直接初始化(不使用等号)。
3.2.2 string对象上的操作
1、使用getline读取一整行(直接读只会读一个单词,从第一个不是空白符的字符开始,直到遇到空白符就停),其中getline会读入换行符,但是不会把它写入目标对象。
2、string的size()函数返回类型是string::size_type类型,允许编译器通过auto或者decltype来推断变量的类型。
3、当把string对象和字符字面值或字符串字面值相加时,必须确保每个加法运算符的两侧运算对象至少有一个是string。注意:字符串字面值并不是string对象。
3.2.3 处理string对象中的字符
1、建议:使用C++版本的C标准库头文件(P82)
2、范围for语句:P82
3、在范围for循环中,如果想改变string对象中字符的值,必须将循环变量定义为引用类型。
4、可使用下标访问字符串中的字符,使用超出范围的下标将引发不可预知的结果,以此推断,使用下标访问空string也会引发不可预知的结果。
5、关于string对象是否以空字符'\0'结尾,我还没有搞清楚......
3.3 标准库类型vector
1、vector是一个类模板,使用vector时我们需要提供一些额外信息(存放对象的类型)来指定模板到底实例化成什么样的类。
3、初始化vector时,编译器会综合初始化的形式(圆括号or花括号)以及传递的参数类型,来确定执行何种初始化。(P89:列表初始化还是元素数量?)
4、向vector中添加元素:push_back函数。比较好的做法是:开始时先创建空的vector对象,运行时再动态添加元素。需要注意的是,对于循环,如果循环体内包含有向vector对象添加元素的语句,则不能使用范围for循环。
5、不能用下标形式添加元素!只能对确知已存在的元素执行下标操作!确保下标合法的一种有效手段就是尽可能使用范围for语句。(P94)
2、值初始化:如果vector对象的元素是内置类型,比如int,则值初始化为0;如果元素是某种类类型,比如string,则元素由类默认初始化。
3.4 迭代器介绍
1、如果容器为空,则begin和end返回的是同一个迭代器,都是尾后迭代器(指向容器“尾元素的下一位置”)。
2、P97:关键概念:泛型编程。C++程序员在for循环中习惯性地使用!=而不用<,其原因和他们更愿意使用迭代器而非下标的原因一样:因为这种编程风格在标准库提供的所有容器上都有效。
3、C++11新增cbegin和cend函数,他们返回const_iterator类型(迭代器只能读元素,不能写元素)。
4、箭头运算符:将解引用和成员访问两个操作结合在一起:it→mem等价于(*it).mem。
5、任何可能改变vector对象容量的操作,比如push_back,都会使该vector对象的迭代器失效。
3.5-3.6 数组与多维数组
3.5.1 定义和初始化内置数组
1、数组的维度必须是一个常量表达式。
2、用字符串字面值初始化字符数组时,要注意字符串字面值结尾还有一个空字符,字符数组需要有足够的容量存储这个空字符。
3、不能将数组的内容拷贝给其他数组作为其初始值,也不能用数组为其他数组赋值。一些编译器支持数组的赋值,这就是所谓的编译器扩展(compiler extension)。但一般来说,最好避免使用非标准特性,因为含有非标准特性的程序很可能在其他编译器上无法正常工作。
4、要想理解数组声明的含义,最好的办法是从数组的名字开始按照由内向外的顺序阅读。
3.5.2 访问数组元素
3.5.3 指针和数组
1、在大多数表达式中,使用数组类型的对象其实是使用一个指向该数组首元素的指针。
2、当数组作为一个auto变量的初始值时,推断得到的类型是指针;当使用decltype关键字时,返回类型是数组。
3、只要两个指针指向同一个数组的元素,或者指向该数组的尾元素的下一位置,就能利用关系运算符进行比较。如果两个指针分别指向不相关的对象,则不能比较它们。
4、内置的下标运算符所用的索引值不是无符号类型,可以为负,这一点与标准库不一样。p[-2] = *(p - 2)。
3.5.4--3.6 C风格字符串~~多维数组
1、对大多数应用来说,使用标准库string要比使用C风格字符串更安全、更高效。
2、建议:尽量使用标准库类型而非数组(P112)
3、要使用范围for语句处理多维数组,除了最内层的循环外,其他所有循环的控制变量都应该是引用类型(P114)
4、使用for循环遍历多维数组时,类型判断是个很麻烦的事(尤其是涉及指针时)。可以利用auto,decltype或者类型别名来处理这样的事情(P115-P116)
作业题
练习3.26:不存在迭代器+迭代器的运算。
练习3.34:程序的功能等同于p2 = p1。在p1本身是常量,即顶层const时,该程序是非法的。
练习3.43:代码如下:
#include <iostream>
#include <string>
using namespace std;
int main()
{
int ia[3][4] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
for (int(&row)[4] : ia) {
for (int col : row)
cout << col << " ";
cout << endl;
}
for (size_t row = 0; row != 3; row++) {
for (size_t col = 0; col != 4; col++)
cout << ia[row][col] << " ";
cout << endl;
}
for (int(*row)[4] = ia; row != ia + 3; row++) {
for (int *col = *row; col != *row + 4; col++)
cout << *col << " ";
cout << endl;
}
}