Day 3
完成了 C++ Primer 第 4, 5 章的阅读
-
常量迭代器,不能修改其所指向的对象,可以移动它,
vector<int>::const_iterator it = v.begin();
,常量容器只有常量迭代器。 -
标准容器
.size()
返回xxx::size_type
无符号类型,迭代器加减运算返回difference_type
有符号类型。 -
指向数组的指针:
int (*p)[10] = &arr; int (&arrRef)[10] = arr
p 指向一个长度为 10 的数组,arrRef 引用一个含有 10 个整数的数组。- 相减的运算结果类型是有符号类型的
ptrdiff_t
定义在cstddef
中。
- 相减的运算结果类型是有符号类型的
-
数组中的 begin 与 end。在 C++ 11 标准以上,对数组 a 使用
begin(a),end(a)
返回首尾元素指针。- 数组初始化 vector,
vector<int> vec(begin(arr), end(arr));
。
- 数组初始化 vector,
-
for 循环遍历多维数组,除了最内层的循环,外层循环都应使用引用类型。
-
左值、右值:作为右值用的是对象的值;作为左值,用的是对象的身份(在内存的位置)。
- decltype 作用于左值得到引用类型,如
int* p
,decltype(*p)
得到int&
,decltype(&p)
得到int**
。
- decltype 作用于左值得到引用类型,如
-
小习惯:
*iter++
取得迭代器原来的值后,迭代器向后移,++运算符优先级高于解引用*运算符。- 注意 UB:
while (it != s.end() && !isspace(*beg)) *beg = toupper(*beg++)
这是未定义行为,等式两边都使用了 beg,求值顺序是未定义的,应该避免。
- 注意 UB:
-
命名的强制类型转换。
cast-name<type>(expr)
- static_cast: 具有明确定义的类型转换,不包含底层const,都可以使用static_cast。
double slope = static_cast<double>(j)
- const_cast: 只能改变运算对象的底层 const。去掉表达式的 const 属性,例如可以将
const char*
作为char*
的初始值。 - reinterpret_cast:向较低层次转换,如 int* 赋值给 char* ,但会有一些未知的危险,编译器不会检查。
- static_cast: 具有明确定义的类型转换,不包含底层const,都可以使用static_cast。
-
exception 头文件定义了最常用的异常类 exception 。
-
new 头文件定义了
bad_alloc
异常类。 -
type_info 头文件定义了
bad_cast
类型。 -
<stdexcept>
定义的异常类。exception, runtime_error, range_error, overflow_error, underflow_error
logic_error, domain_error, invalid_argument, length_error, out_of_range
- 使用
.what()
获取初始化时返回的错误信息。
-
函数实参的求值顺序没有明显规定,慎用调用函数结果作为实参 。
-
多文件链接:
# f.h 声明 f(), f.cpp 定义 f(), main.cpp 使用 f()
# f.cpp 包含 f.h,main.cpp 包含 f.h
g++ -c f.cpp # 产生 f.o
g++ -c main.cpp # 产生 main.o
g++ f.o main.o -o main # 产生 main 可执行文件
- 向 main 函数传递参数:
// ./main a1 a2
int main(int argc, char** argv) { // argc 参数个数(3),argv 二维字符串,argv[0] 是程序名
// statement
return 0;
}