1 using声明
- 方便使用命名空间中的成员,不用每次xxx::yyy
-
头文件不应该包含using声明(不经意间包含了一些名字)
2 string
表3.1:初始化string对象的方式 |
|
string s1 |
默认初始化,s1是空串 |
string s2(s1) |
s2是s1的副本 |
string s2 = s1 |
等价于s2(s1) |
string s3(“value”) |
s3是字面值”value”的副本,除了最后空格符 |
string s3 = “value” |
等价于s3(“value”) |
string s4(n, ‘c‘) |
s4初始化为有连续n个字符c组成的串 |
表3.2:string的操作 |
|
os<<s |
将s写到输出流os当中,返回os |
is>>s |
从is中读取字符串赋给s,遇到空白结束,返回is |
getline(is, s) |
从is中读取一行赋给s,返回is |
s.empty() |
s为空返回true |
s.size() |
返回s中字符的个数 |
s[n] |
返回s中第n个字符的引用,n从0开始计起 |
s1+s2 |
返回s1和s2链接后的结果 |
s1=s2 |
用s2的副本代替s1中原来的字符 |
s1==s2 |
|
s1!=s2 |
|
<, <=, >, >= |
|
- string对象会自动忽略开头的空白(即空格符、换行符、制表符)并从第一个真正的字符开始读起,知道遇到下一处空白为止。
- getline保留输入时的空白符,只要一遇到换行符就结束并返回结果,得到的string对象不包含该换行符。
- size函数返回string::size_type类型的值,是一个无符号类型的值,而且能足够存放下任何string对象的大小。如表达式中已有size()函数就不要再用int了,可以避免混用可能带来的问题。
-
比较依照字典顺序,较短的string每个字符都与较长的一样,则较短的string小。如不一样,则为第一对相异字符的比较结果。
处理string中的字符
表3.3:cctype头文件中的函数 |
|
isalnum(c) |
c为字母或数字时为真 |
isalpha(c) |
字母 |
iscntrl(c) |
控制符 |
isdigit(c) |
数字 |
isgraph(c) |
不是空格但可打印时 |
islower(c) |
小写字母 |
isprint(c) |
可打印字符(空格或c具有可视形式) |
ispunct(c) |
标点符号(不是控制字符、数字、字母、可打印空白) |
isspace(c) |
空白(空格、横向制表符、纵向制表符、回车符、换行符、进纸符) |
isuppper(c) |
大写字母 |
isxdigit(c) |
十六进制数字 |
tolower(c) |
转小写 |
toupper(c) |
转大写 |
范围for,适合要处理string对象中每一个字符
- for (declaration : expression) statement
-
expression是一个对象,表示一个序列。declaration定义一个变量,用于访问序列中的基础元素。每次迭代,declaration的变量会被初始化为expression部分的下一个元素值。
-
如想改变string对象中字符的值,必须把循环变量定义为引用类型。
-
如果只是处理某些字符,使用下标或迭代器。使用下标时必须清楚地知道它是否在合理的范围之内。下标可用于访问已存在的元素。
3 vector
-
早期版本中,vector<vector<int> >,需要添加一个空格。
- 初始化过程会尽可能地把花括号内的值当做是元素初始值得列表来处理。
- 如果循环体内包含有向vector对象添加元素的语句,则不能使用for循环。for循环中预存了end()的值,一旦添加或删除元素,end()函数的值可能变得无效
初始化的方法
v1, v2(v1), v2=v1, v3(n, val), v4(n), v5{a,b,c...}, v5={a,b,c...}
初始化过程会尽量将花括号内的值当成是元素初始值列表来处理。
列表初始化和聚合初始化
[new] T [object] { arg1, arg2, ... };
- 如果T是aggregate类型,list中的参数对object成员逐个初始化;或者,
- 如果T不是aggregate类型,编译器查找最匹配list参数的T的构造函数。
值初始化
[new] T [object] {};
如果只提供了元素,而没给初始值,则进行值初始化。
- 如果T有用户定义的缺省构造函数,直接调用;
- 如果T有编译器生成的缺省构造函数,先0值初始化再调用;
- 如果T是内置类型,直接0值初始化。
缺省初始化
[new] T object;
缺省初始化除了在值初始化过程中可能进行之外,也可以以上面形式单独进行。这种初始化的独特地方在于,如果T是非class类型,则给出非确定值。兼容C的行为。
零值初始化
static T object;
0值初始化除了在值初始化过程中可能进行之外,也可以单独作用于静态(或者线程局部)变量
直接初始化
[new] T [object] ( arg1, arg2, ... );
拷贝初始化
传参,返回值,=定义
4 迭代器
- 所有标准库容器的迭代器都定义了==和!=。
- 如果对象只需读操作而无需写操作,最好用常量类型cbegin和cend。
- 箭头运算符把解引用和成员访问两个操作结合在一起。
- 任何一种可能改变vector对象容量的操作,比如push_back,都会使得该vector对象的迭代器失效。
- 迭代器之间距离 different_type带符号整型数。
5 数组
- 数组的大小确定不变,不能随意向数组中添加元素。不允许拷贝和赋值。
-
理解复杂的数组声明,默认情况下类型修饰符从右往左依次绑定。最好从数组名字开始由内向外顺序阅读。
int *ptrs[10]; //ptrs是含有10个整型指针的数组 int &refs[10] = ???; //不存在引用的数组 int (*Parray) [10] = &arr; //Parray指向一个含有10个整数的数组 int (&arrRef) [10] = arr; //arrRef引用一个含有10个整数的数组
- 对数组的很多操作,编译器都是自动将其替换为一个指向数组首元素的指针。
- 当使用数组作为一个auto变量的初始值时,得到的类型是指针而非数组。
- 而使用decltype时则不会发生这种转换。
数组下标通常定义为size_t类型,机器相关无符号类型,cstddef头文件中。
指针相减类型ptrdiff_t,带符号类型,也定义在cstddef头文件中。
内置的下标运算符所用的索引值不是无符号类型,这一点和vector string不同。
6 C风格字符串
- 使用标准库string比使用C风格字符串更加安全和高效。
- 出现字符串字面值的地方都可以用 以空字符结束的字符数组来替换。
- 从string返回一个C风格字符串,即返回一个指针指向以空字符结束的字符数组。
- c_str返回的数组不保证一直有效,可能后续操作s的值改变之后,之前返回的数组就失去了效用。想一直使用,最好重新拷贝一份。
用数组初始化vector对象
vector<int> ivec(begin(int_arr), end(int_arr));
尽量使用vector和迭代器,避免使用内置数组和指针。尽量使用string,避免C风格的基于数组的字符串。
7 多维数组
范围for语句,把循环控制变量声明成引用类型,除了最内层的循环外
1是因为要改变元素的值
2是为了避免数组被自动转化成指针,导致内层循环不合法
3避免对元素的拷贝。