一、命名空间的using声明
using namespace :: std;
1、头文件不应包含using声明。因为头文件中的内容会拷贝到所有引用它的文件中去,若头文件中有某个using声明,那么每个使用了该头文件的文件都会有这个声明,可能产生始料未及的名字冲突。
二、标准库类型string
string表示可变长的字符序列。
定义和初始化string对象
1、若提供一个字符串字面值初始化string,则该字面值中除了最后那个空字符外其他所有的字符都被拷贝到新创建的string对象中去。
直接初始化和拷贝初始化
使用等号(=)初始化一个变量,实际上执行的是拷贝初始化,若不使用等号,则执行的是直接初始化。
stirng对象上的操作
读写string对象
1、使用IO操作符读写string对象,在执行读取操作时,string对象会自动忽略开头的空白(即空格符、换行符、制表符等)并从第一个真正的字符开始读起,直到遇见下一处空白为止。
2、使用getline读取一整行,有时我们希望能在最终得到的字符串中保留输入时的空白符,这时应该用getline函数代替原来的>>运算符。读取时换行符也被读进来了,但是不会把换行符存入string对象。
string::size_type
size函数返回的是一个string::size_type类型的值。
1、如果一条表达式中已经有了size()函数就不要再使用int了。这样可以避免混用int和unsigned可能带来的问题。
2、当把string对象和字符字面值及字符串字面值混在一条语句中时,必须确保每个加法运算符的两侧的运算对象至少有一个时string
3、C++语言中的字符串字面值并不是标准库类型string对象。
处理string对象中的字符
使用for语句处理每个字符·:
for(declaration: expression)
statement
## 使用范围for语句改变字符串中的字符
若想要改变string对象中字符的值,必须把循环变量定义成引用类型。
三、标准库类型vector
1、vector是模板而非类型,由vector生成的类型必须包含vector中元素的类型,例如vector。
定义和初始化vector对象
1、若用圆括号,提供的值是用来构造vector对象的,说明了vector对象的容量
2、若用的花括号,则是列表初始化该vector对象
3、若初始化时使用了花括号的形式但提供的值又不能用来列表初始化,就要考虑用这样的值来构造vector对象
向vector对象中添加元素
push_back();
1、size返回vector对象中元素的个数,返回值的类型是由vector定义的size_type类型。
2、要使用size_type,需首先指定它是由哪种类型定义的,vector对象的类型总是包含着元素的类型。
3、vector对象(以及string对象)的下标运算符可用于访问已存在的元素,而不能用于添加元素。
迭代器
1、迭代器有有效和无效之分,有效的迭代器或者指向某个元素,或者指向容器中尾元素的下一位置,其他所有情况都属于无效。
2、有迭代器的类型同时拥有返回迭代器的成员,如,这些类型都拥有名为begin和end的成员,其中begin成员负责返回指向第一个元素的迭代器,end成员则负责返回指向容器“尾元素的下一位置”的迭代器(尾后迭代器)。
迭代器运算符
1、for循环中使用 != 而非 < 进行判断。因为所有标准库容器的迭代器都定义了 ==和 !=,但是它们中大多是都没有定义 <运算符,与之类似,只有string和vector等一些标准库类型有下标运算符,而非全都如此所以建议使用迭代器。
迭代器类型
1、就像不知道string和vector的size_type成员到底是什么类型一样,一般来说我们也不知道(其实是无须知道)迭代器的精确类型。而实际上,那些拥有迭代器的标准库类型使用iterator和const_iterator来表示迭代器的类型。
2、如果vector或string对象是常量,那么只能使用const_iterator。
3、begin和end返回的具体类型由对象是否是常量决定,若对象是常量,begin和end返回const_iterator,若对象不是常量,返回iterator。
4、为了便于专门得到const_iterator类型的返回值,C++11新标准引入了两个新函数,分别是cbegin和cend。
5、但凡是使用了迭代器的循环体,都不要向迭代器所属的容器添加元素。会使迭代器失效。
迭代器运算
1、只要两个迭代器指向的是同一个·容器中的元素或者尾元素的下一位置,就能将其相减,所得结果是两个迭代器的距离。所谓距离指的是右侧迭代器向前移动多少位置就能追上左侧的迭代器,其类型名为difference_type的带符号整型数。
四、 数组
定义和初始化内置数组
1、定义数组的时候必须指定数组的类型,不允许用auto关键字。
2、数组的元素应为对象,因此不存在引用的数组。
显示初始化数组元素:
字符数组的特殊性:
可用字符串字面值对字符数组初始化,当使用这种方式时,一定要注意字符串字面值的结尾处还有一个空字符,这个空字符也会像字符串的其他字符一样被拷贝到字符数组中去。
不允许拷贝和赋值:
不能将数组的内容拷贝给其他数组作为其初始值,也不能用数组为其他数组赋值:
复杂的数组声明
指针和数组
1、当使用数组作为一个auto变量的初始值时,推断得到的类型是指针而非数组。
2、decltype(ia)返回的类型是由10个整数构成的数组。
两个指针相减的结果的类型是一种名为ptrdiff_t的标准库类型,和size_t一样,ptrdiff_t也是一种定义在cstddef头文件中的机器相关的类型,因为差值可能为负值,所以ptrdiff_t是一种带符号类型。
指针也是迭代器
就像使用迭代器遍历vector对象中的元素一样,使用指针也能遍历数组中的元素,包括尾元素的下一位置的指针。
一个指针如果指向了某种内置类型数组的尾元素的“下一位置”,则其具备与vector的end函数返回的与迭代器类似的功能。
不能对尾后指针执行解引用或递增的操作。
标准库函数begin和end
为了让指针的使用更简单、更安全,C++11新标准引入了两个名为begin和end的函数。
两个函数定义在iterator头文件中。
混用string对象和C风格字符串
若程序的某处需要一个C风格字符串,无法直接用string对象来代替它。
为了完成该功能,string专门提供了一个名为c_str的成员函数。
我们无法保证c_str函数返回的数组一直有效,若后续的操作改变了s的值就可能让之前返回的数组失去效用。
若执行完c_str()函数后程序想一直都能使用其返回的数组,最好将该数组重新拷贝一份。
使用数组初始化vector对象
使用数组的一部分初始化vector
五、多维数组
多维数组的初始化
使用范围for豫剧出力多维数组
因为要改变数组的值,所以选用引用类型作为循环控制变量。
这个循环中并没有任何写操作,但我们还是将外层循环的控制变量声明成了引用类型。这是为了避免数组被自动转成指针。
若不用引用类型
程序将无法通过编译,因为row会转换成指向该数组内首元素的指针,这样得到的row类型就是是int*,显然内层的循环就不合法了,编译器将试图在一个int*内遍历。
要使用范围for语句处理多维数组,除了最内层循环外,其他所有循环的控制变量都应该是引用类型。
指针和多维数组
当程序使用多维数组的名字时,也会自动将其转换成指向数组首元素的指针
由多维数组名转换得来的指针实际上是指向第一个内层数组的指针。
通过使用auto或者decltype就能尽可能地避免在数组前面加上一个指针类型了:
使用标准库函数begin和end