1. 头文件预处理
为确保头文件多次包含仍能安全工作,因此加入头文件保护符(header guard)
#ifndef HEADFILE_H
#define HEADFILE_H
…
#endif
2. 迭代器
以vector为例,通常我们采用vector<\int>::iterator it;的形式进行跌带起的定义,但更方便的是使用auto。
例如:for(auto it=v.begin(); it!=v.end(); it++);
迭代器在使用时,不能在范围for循环(或者while等)中使用向vector中添加元素的操作,例如push_back(),这样会使已有的跌带起失效。
因为迭代器可以通过与整数进行+/-的操作,因此两个迭代器相减即可获得他们所指位置之间的距离,同时也可以通过与整数加减进行移位操作,当然也可以进行二分搜索。
3. 数组
数组定义的时候必须指定数组的类型,不允许使用auto关键字由初始值列表进行推断。
和vector一样,数组的元素必须是对象,不存在引用的数组。但是数组可以被其它引用。例如
int *ptrs[10]; //含有10个整型指针的数组
int (*Parray)[10]=&arr; //Parray指向一个含有10个整型的数组
int (&arrRef)[10]=arr; //arrRef引用一个含有10个整数的数组
4. 强制转换
格式:cast-name<\type>(expression);
其中type是转换的目标类型,expression是要转换的值,cast-name包括static_cast、dynamic-cast、const-cast和reinterpret_cast。
static_cast:任何具有明确定义的类型转换,只要不包括底层const,都可以通过static_cast进行转换。
const_cast:只能呢个改变运算对象的底层const。
reinterpret_cast:通常为运算对象的位模式提供较低层次上的重新解释。
除此之外还有表达式常量,限定于编译阶段。
5. 异常处理
一定要养成异常处理的好习惯
常见的异常类:
exception (最常见的问题)
runtime_error (只有在运行时才能检测出的问题)
range_error (生成的结果超出了有意义的值域范围)
overflow_error (计算上溢)
underflow_error (计算下溢)
logic_error (程序逻辑错误)
domain_error (参数对应的结果只不存在)
invalid_argument (无效参数)
length_error (视图创建一个超出该类最大长度的对象)
out_of_range (使用一个超出有效范围的值)
try{
......
}
catch(exception e){
cout<<e.what()<<endl;
}
6. 可变形参的函数
void fun(int a,...) {
va_list ap;
__crt_va_start(ap, a);
int x = -1;
for (int i = 0; i < a; i++) {
x = __crt_va_arg(ap, int);
cout <<i+1<<"->"<< x << endl;
}
}
int main() {
fun(0);
fun(1, 2);
fun(2, 1, 2);
fun(3, 1, 2, 3);
return 0;
}
7. 返回数组指针
返回数组指针的函数形式:Type (*functon(parameter_list))[dimension]
函数一定不能返回局部数组的指针
也可以使用decltype关键字声明返回类型。
int odd[]={1,3,5,7,9};
int even[]={0,2,4,6,8};
decltype(odd) *arrPtr(int i){
return (i%2)?&odd:&even;
}
8. 函数指针
函数指针指向的是函数而非对象,例如。
bool lengthCompare(const string &, const string &);
bool (*pf)(const string &, const string &);
其中*pf两端的括号必不可少,如果不写括号,则变成了一个返回值是bool型指针的函数,函数名为pf