1. 名字空间
作用域操作符::,作用域操作符的含义是,编译器应从操作符左侧的名字空间去寻找右侧的名字。 使用using 声明即可无需作用域操作符去访问名字。格式如下:
每个using 声明引入命名空间的一个名字,每个名字都需要独立的using声明。 注意在使用中,头文件一般不使用using声明。可能导致包含该头文件的程序包含了这个名字程序员不知道。
2. 标准库类型string
2.1 string初始化
使用等号进行初始化的方式是拷贝初始化 ,是将等号右侧的值拷贝到新创建的对象内。 不使用等号的方式称为直接初始化
2.2 读写string
2.2.1 cin
使用cin>> 运算符。cin 会忽略开头的空白,从第一个真正的字符读起,直到遇到下一个空白。cin 是IO库中的一个对象,cin 会返回其左侧的对象作为运算结果,所以可以将多个cin 串起来实现连续读取。
可用cin>> 返回值判断是否到达文件结尾或者是否读到非法输入。
2.2.2 getline
getline 的参数是一个流对象和一个用于接收字符的string,效果是从输入流中读取数据直到遇到换行符为止,包含换行符,然后把数据转存到string内,不存换行符。 如果数据一开始就是一个换行符,将生成一个空的string。 注意一个细节,line中不包含换行符。
2.3 string的empty和size
empty 用法: size 返回string中字符 的个数: 通过调用size函数得到的返回值是一个size_type类型的值,size_type是一个无符号类型的值,且能存放下任何string对象的大小。C++中大多苏标准库类型都会有几种配套的类型,目的是让标准库类型与机器无关。
在表达式混用有符号数和无符号数? 负值会自动转化为一个很大的无符号数,可能带来意想不到的后果。
2.4 string的运算
标准库允许将字面值转化为string类型。但是注意,当string和字面值混用时,必须确保"+"运算符两侧的运算对象至少有一个是string。
2.5 处理string对象内的字符
2.5.1 遍历for
可使用范围for循环 : string正是一个字符序列,故可用如下方式访问string:
2.5.2 修改string
想要修改string,必须将循环的变量设为引用。如下:
2.5.3 部分处理string
下标:下标运算符([ ])接收string::size_type类型的参数,带符号类型的参数会被转为size_type类型。下标运算符会返回该位置上的元素的引用。
3. 标准库类型vector
vector 是一个类模板。模板不是类或者函数,是编译器生成类或者函数的说明。编译器需要根据模板创建类或者函数,这个过程称为实例化。实例化时,需要指明实例化为何种类型。 比如: 如上所展示的vector< int >,vectoe<Sales_item>等等都是类型,是由编译器根据vector模板生成的。
vector以对象作为元素,所以不存在包含引用的vector。
3.1定义和初始化vector对象
等号(拷贝初始化),圆括号(直接初始化),花括号(列表初始化)都可以使用。圆括号不能直接跟等于,除非在等于右侧显式的创建一个新对象,效果同第二和第三种初始化方法。 另外注意,使用拷贝初始化时,两个vector对象的元素类型必须相同。 在利用列表初始化时,如果提供的值无法进行列表初始化,那么就会尝试用提供的值进行直接初始化: 如图,尽管是花括号,但是由于提供是和对象元素不一致类型的值,最终完成的是直接初始化。
3.2 向vector内添加新值
push_back :
3.3 vector相关操作
访问vector的操作和访问string的操作几乎一致。 如上是访问以及修改vector元素的方法。 vector的size函数返回值也是size_type,注意,是vector所实例化的类型的size_type,如下: 关于vector比较的一些说明:
3.4 vector的副作用
1.不能在范围for循环内向vector中添加元素 2.任何可能该边vector容量的操作,比如Push_back,都会使该vector对象的迭代器失效。
4. 迭代器
如果一个类型具有迭代器,也会有名为begin 和end 的成员,使用这些成员会返回迭代器,begin 返回指向第一个元素的迭代器,end 返回指向最后一个元素的下一位置的迭代器。
在容器为空的情况下,begin和end返回的是同一迭代器。
可通过节引用迭代器获取迭代器指向的元素。该迭代器必须有指向某个元素,否则是未定义的行为。
可使用加一操作移动迭代器。不能移动未指向元素的迭代器,比如end 。
具有迭代器的标准库类型使用iterator 和const_iterator 表示迭代器,如下: 具体是iterator 还是const_iterator 由使用begin和end运算符的对象类型决定,如果对象是常量,则返回的迭代器类型为const_iterator 。在某些应用场景里,可能对非常量的对象只想读,可使用cbegin 和cend 获取const_iterator 类型的迭代器。
C++的-> (箭头运算符),结合了解引用和访问成员两个操作,即:
4.1 迭代器运算
所有的标准库容器的迭代器都能进行递增运算++ ,以及能用== 和!= 对两个迭代器进行比较。 vector 和string 的迭代器有更多的额外运算符: 迭代器相减得到的结果的数据类型是名为difference_type 的带符号整形。
5.数组
数组的维度必须是一个常量表达式 。 默认情况下,数组的元素被默认初始化。也就是说,如果数组被定义在函数内,那么默认初始化会让数组含义未定义的值。
同样的,数组元素也应该是对象,不存在引用的数组。
5.1 数组初始化
允许对数组进行列表初始化,此时,可以忽略数组的维度,编译器会根据初始值数量计算出来。 如果指明了数组维度,初始值数量不应超过该维度值,如果维度大于初始值的数量,使用提供的初始值初始化靠前 的元素,剩下的元素被初始化为默认值 。 对字符数组初始化有一个注意事项,允许使用字符串字面值初始化字符数组,但是注意字符串字面值结尾还有一个空字符"\0" 也会被拷贝到数组内。
不能把数组内容拷贝给其他数组作为初始值,也不能用数组为其他数组赋值。 不能使用vector初始化数组,但是反过来可以。
5.2 复杂的数组声明
从内向外(标识符有括号先读括号) ptr,没有括号,从内向外,可以看到[10]表示声明的是一个长度为10的数组。名为ptr,最后判断左侧的,数组元素类型为int*; parray,有括号,先从内向外,得到parray是一个指针,指针指向的是一个长度为10的数组最后判断左侧的,数组里面的元素是int; 更进阶的情况: 同样的,先从内向外,arry是一个引用,引用了一个长度为10的数组,最后判断左侧的,数组元素的int*; 对于这个arr,先从内向外,是一个长度为10的数组,数组元素是长度为20的数组,长度为20的数组的数组元素是长度为30的数组,长度为30的数组的数组元素从右向左可以看到是int。
5.3 访问数组元素
数组的下标被定义为size_t 类型,是一种机器相关的无符号类型。 也可用范围for循环 访问数组元素:
在一般情况下,数组名对应的数组第一个元素的地址。但是使用decltype 返回的类型是数组,并且大小、元素类型都和原数组一样。 可以使用超过数组范围的索引获得尾后地址。但是不能对该尾后地址解引用或者递增,只能向end 一样做一个标志。比如对一个有9个元素的数组arr,&arr[9]就是尾后地址。 如果对尾后元素解引用会得到一个警告,再往后的元素解引用就会报错。 尾后指针可以参与和同一数组正常指针的比较
数组元素也有类似于容器的begin 和end ,但是数组毕竟不是类类型,所以没有成员函数,正确的做法是将数组作为begin 和end 的参数。说明如下: 注意和容器不同的是,begin和end返回的不是迭代器而是指针。 指针相减: 指针比较: 空指针和所指对象非数组的指针也可以比较。后一种情况相比较的两个指针必须指向同一对象或者指向对象的下一位置 。
对数组的下标运算是内置的下标运算,参数可以是负值(前提是结果地址必须和原来的指针指向同一数组元素)。标准库类型vector、string的下标运算参数必须是无符号类型。
5.4 C风格字符串
字符串字面值是C++由C继承而来的C风格字符串。 上述函数的参数必须是以空字符结尾的字符数组。
5.5 与旧代码接口
字符串字面值->string: 1.任何字符串字面值都可用以空字符结尾的字符数组代替。 2.允许使用以空字符结尾的字符数组初始化和赋值string对象 3.string对象加法运算中允许一个参数是以空字符结尾的字符数组。
string->以空字符结尾的字符数组: 使用c_str 函数: c_str 函数返回一个指向以空字符结尾的字符数组的指针。指针类型为const char* ;c_str 返回的数组在修改了s之后可能失效。 可以使用数组初始化vector,只需指明拷贝的首元素地址和尾后地址 即可:
5.6 多维数组
使用范围for循环遍历多维数组: 除了最内层外的外层必须声明为引用,无论是否要修改数组的元素:
|