导言###
程序设计语言中充满陷阱,一不小心就会掉入其中万劫不复,之所以有陷阱,是因为语言的设计细节不符合程序员的直觉
所以你会发现,语言越高级越注重顺从程序员的直觉。
c++也有许多陷阱,所谓山不过来,我就过去,因此将c++中易错点、难点集合于此,会不定期更新。
参考:c++中的陷阱(一)
控制语句###
-
在swtich语句中存在一个普遍的误解,以为程序只会执行匹配的case标号相关联的语句,实际上,程序从该点开始执行,并跨越case边界继续执行其他语句,直到swtich结束或遇到break
-
对于switch结构,只能在它的最后一个case标号或default标号后面定义变量,这是为了避免出现代码跳过变量的定义和初始化的情况。如果需要为某个特殊的case定义变量,则可以引入块语句,在该块语句中定义变量,从而保证这个变量在使用前被定义和初始化。
char c = 'b';
switch(c){
case 'b':
{
int i = 0; //right i定义在语句块中
cout<<"b"<<endl;
}
case 'c':
cout<<"c"<<endl;
default:
;
}
char c = 'b';
switch(c){
case 'b':
int i = 0; //error
cout<<"b"<<endl;
case 'c':
cout<<"c"<<endl;
default:
;
}
- do-while语句中,任何在循环条件中引用的变量都必须在do语句之前就已经存在
string input;
do{
cout<<input<<endl;
cin >> input;
}while(input != "bye"); //right
do{
string input;
cout<<input<<endl;
cin >> input;
}while(input != "bye"); //error 变量input只存在于花括号的块作用域中
while(bool status = true){ //right
cout<<"hello"<<endl;
}
do{
cout<<"hello"<<endl;
}while(bool status = true); //error 变量status必须在do语句之前就已经存在
函数###
- 返回值为void的函数,return后一般不能接表达式,但有一个例外,即返回另一个返回类型同样是void的函数的调用结果
void func1(){}
void func2(){return func1();} //right
int main(){
func2();
return 0;
}
-
函数的返回值是引用类型时,谨记不能返回局部对象的引用。因为在函数执行完毕时,将释放分配给局部对象的存储空间,此时,对局部对象的引用就会指向不确定的内存
-
函数的返回值是指针时,谨记不能返回局部对象的指针,理由同上
-
返回引用的函数返回一个左值,因此可以给返回的引用赋值
int &func(int &i){return i;}
int main(){
int ival = 0;
cout<<ival<<endl; // 0
func(ival) = 1; //func返回引用,因此返回的是一个左值
cout<<ival<<endl; // 1
return 0;
}
-
const对象、指向const对象的指针或引用只能用于调用其const成员函数,如果尝试用他们调用非const成员函数,则是错误的
-
区分重载与非重载
非重载
int func(const int i);
int func(int i);
int func(int *const i);
int func(int *i);
typedef int integer;
int func(int i);
int func(integer i);
void fun(int i=0);
void fun(string s="");
重载
int func(const int &i);
int func(int &i);
int func(const int *i);
int func(int *i);
- 重载函数的实参类型转换
int func(int i){ cout<<"int func"<<endl;}
int func(unsigned char){ cout<<"unsigned char func"<<endl;}
int main(){
char c = 'a';
func(c); //打印 int func
}
/*
char类型到int型是类型提升,char类型到unsigned char类型是类型转换,在实参匹配时类型提升优于类型转换
实参类型的转换等级:1.精确匹配 2.通过类型提升 3.通过标准转换 4.通过类类型转换
*/
int func(int i, int ii){ cout<<"int func"<<endl;}
int func(double d, double dd){ cout<<"double func"<<endl;}
int main(){
int i=0;
double d=0.0;
func(i,d); //error 二义性
}
/*
在调用重载函数时,编译器会试图寻找最佳匹配,若无法确定唯一的最佳匹配,则报错
*/
enum ABC {a, b, c};
int func(ABC val){}
int main(){
ABC v = a;
func(v); //right
func(1); //error 不能直接将整数值作为枚举类型的实参
}