1 悬垂else来自于else语句搭配的if语句的二义性
2 理解switch代码:
switch(c) { case 'a': a++; case 'b': b++; default: x++; }
如果为'a',则a++,b++,x++都会被执行
如果为'b',则b++,x++都会被执行
如果都不是,则只执行x++
由此可以推测出switch语句中break的作用,以及没有break时,语句的执行情况:第一个满足的case一直执行到break或switch结束,之后所有的case都被忽略,退出之前所有的语句都会被执行
3 switch结构内定义的变量,只能在最后一个case标号或default标号后面定义,防止代码出现跳过变量的定义和初始化的情况
因为定义过的变量可以被之后的代码使用,但是switch结构中,可能会跳过定义直接到达变量使用的代码处
如果某个case需要定义变量,最好使用{},防止之后的case继续使用该变量
4 *p1++ = *p2++
后自增操作符优先级高于*操作符,所以自增的是指针,不是指针指向的对象,但是解引用是从第一个元素开始,即对于p1和p2,其值已经实现自增,但是对于表达式*,还是p1和p2自增之前的值
不能按照p1和p2自增,然后对其自增后的值解引用,因为p1++的返回值是自增前的p1,虽然p1本身是自增的
5 goto语句不能跨越变量的定义向前跳转
6 函数相关
函数调用:用对应实参初始化函数形参,将控制权转交给被调用函数,主调函数被挂起,被调函数开始执行,被调函数的运行以形参的(隐式)定义和初始化开始,直到return结束,return的结果作为主调函数中调用操作符的结果
非引用和指针形参:const和非const形参,都可以用const或非const实参来调用
引用和指针形参:const形参可以用const或非const实参来调用,非const形参只能用非const实参来调用
使用引用形参的另一个好处是:避免复制实参!!
通过引用传递数组时,数组大小成为实参和形参的一部分:
void func(int (&a)[5]) { for(int i - 0;i < 5;++i) cout << a[i] << endl; }
传递多维数组:matrix是指向指针的指针,这个指针指向10元素的数组的首元素
void printValues(int (*matrix)[10],int rowSize)
默认实参既可以在函数声明中指定,也可以在函数定义中指定,但是一个形参只能指定默认实参一次,通常在函数声明中指定默认实参
7 局部对象
自动对象:函数调用时才存在的对象称为自动对象
静态局部对象:对象位于函数的作用域,但声明周期跨越了函数的多次调用,则称为静态局部对象
8 内联函数
函数内联说明对于编译器来说只是一个建议,编译器可以选择忽略;内联函数一般定义在头文件中
编译器隐式的将在类内定义的函数当做内联函数
9 重载函数
void func(int a) { cout << a << endl; } void func(int a,int b=1) { cout << a << endl; cout << b << endl; } int main() { int x = 1; func(x);//overload ambiguous }
重载函数应该在同一个作用域中声明,否则某个作用域内声明的函数会屏蔽其他作用域声明的同名函数
重载函数匹配二义性是错误的,形参是枚举类型和形参是整型不存在二义性
重载函数实参匹配:精确匹配—类型提升—标准转换—类类型转换
10 通过函数指针调用函数不需要解引用操作符,直接调用
函数指针做形参 returnType(paramList)或 returnType(*)(paramList)
是函数还是函数指针,看名称是与()结合紧密还是与*结合紧密,()优先级高于*