1. 命名空间的using声明
声明命名空间:using namespace::name
,然后就可以直接使用命名空间中的名字。
- 例如
using namespace std;
可以直接使用std
中的cin/out
- 又或者直接使用某个命名空间中的名字:
using std::cin;
头文件不应包含using声明
-
原因:
头文件的内容会拷贝到所有引用它的文件中去,某些文件可能不经意间包含了一些名字,这样会导致冲突
2. 标准库类型string
string::size_type
- string和其它标准库类型都定义了几种配套的类型,这些配套类型体现了与机器无关的特性
- size_type是一个无符号类型的值,足够放下任何一个string对象的大小
字符串常量和string不是同一个类型
处理每个字符?使用基于范围的for语句
for (declaration : expression)
statement;
-
使用这个语句修改string中的字符
for (auto &c: s){ if (isalpha(c)){ c = toupper(c); } }
只处理部分字符?
- 下标索引
3. 标准库类型vector
略
4. 迭代器介绍
某些对vector对象的操作会使得迭代器失效
- for循环中添加元素
- 改变容量的操作,例如push_back
迭代器失效的常见情况
数组型:插入和删除当前迭代器会使后面的迭代器失效
- 删除迭代器后迭代器无法进行运算或解引用,发生运行时错误
- 解决办法是erase函数返回下一个有效迭代器
for (iter = cont.begin(); iter != cont.end();) { (*it)->doSomething(); if (shouldDelete(*iter)) iter = cont.erase(iter); //erase删除元素,返回下一个迭代器 else ++iter; }
链表型:
- 删除当前的iterator,仅仅会使当前的iterator失效,只要在erase时,递增当前iterator即可。
for (iter = cont.begin(); iter != cont.end();) { (*it)->doSomething(); if (shouldDelete(*iter)) cont.erase(iter++); //iter指向下一个迭代器,erase删除当前迭代器 else ++iter; }
树型:
- 插入运算不会使任何迭代器失效
- 删除运算使指向删除位置的迭代器失效,但是不会失效其他迭代器.erase迭代器只是被删元素的迭代器失效,但是返回值为void
5. 数组
一般使用数组的情况是大小已知时,只可以通过常量或者常量表达式定义。
不允许拷贝和赋值
复杂的数组声明
int *ptrs[10];
指针数组int (*ptrs)[10];
指向大小为10的整型数组的指针int &refs[10]=?;
引用数组int (&refs)[10]=&array;
指向大小为10的整型数组的引用
6. 多维数组
多维数组的范围for语句处理
处理二维数组
for (auto &row: ia){
for (auto &col: row){
col = cnt;
cnt++; // 统计元素个数
}
}
-
注意:
这里的col声明为引用是因为col值会被改变,row则必须声明为引用,否则将无法通过编译,因为不声明为引用的话row实际上为一个指向数组的指针,将无法通过内层的范围for循环遍历
指针和多维数组
当程序使用多维数组的名字时,也会自动将其转换成指向数组首元素的指针。
多维数组实际上是数组的数组,所以由多维数组名转换得来的指针实际上是指向第一个内层数组的指针
类型别名简化多维数组
-
例子
using int_array = int[4]; typedef int int_array[4]; int_array *p; // p为指向一个含四个元素的数组的指针