c++中的陷阱(二)

导言###

程序设计语言中充满陷阱,一不小心就会掉入其中万劫不复,之所以有陷阱,是因为语言的设计细节不符合程序员的直觉
所以你会发现,语言越高级越注重顺从程序员的直觉。
c++也有许多陷阱,所谓山不过来,我就过去,因此将c++中易错点、难点集合于此,会不定期更新。
参考:c++中的陷阱(一)


控制语句###

  1. 在swtich语句中存在一个普遍的误解,以为程序只会执行匹配的case标号相关联的语句,实际上,程序从该点开始执行,并跨越case边界继续执行其他语句,直到swtich结束或遇到break

  2. 对于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:
  ;
}
  1. 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语句之前就已经存在

函数###

  1. 返回值为void的函数,return后一般不能接表达式,但有一个例外,即返回另一个返回类型同样是void的函数的调用结果
void func1(){}
void func2(){return func1();}  //right
int main(){
  func2();
  return 0;
}
  1. 函数的返回值是引用类型时,谨记不能返回局部对象的引用。因为在函数执行完毕时,将释放分配给局部对象的存储空间,此时,对局部对象的引用就会指向不确定的内存

  2. 函数的返回值是指针时,谨记不能返回局部对象的指针,理由同上

  3. 返回引用的函数返回一个左值,因此可以给返回的引用赋值

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;
}
  1. const对象、指向const对象的指针或引用只能用于调用其const成员函数,如果尝试用他们调用非const成员函数,则是错误的

  2. 区分重载与非重载
    非重载

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);
  1. 重载函数的实参类型转换
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 不能直接将整数值作为枚举类型的实参
}
posted @ 2014-04-03 13:36  沐恩赖特  阅读(971)  评论(0编辑  收藏  举报