程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++中的陷阱(一)

C++中的陷阱(一)

編輯:C++入門知識

導言   程序設計語言中充滿陷阱,一不小心就會掉入其中萬劫不復,之所以有陷阱,是因為語言的設計細節不符合程序員的直覺   所以你會發現,語言越高級越注重順從程序員的直覺。   c++也有許多陷阱,所謂山不過來,我就過去,因此將c++中易錯點、難點集合於此,會不定期更新。       字符串與vector   字符串字面值與標准庫string不是同一種類型   string s("hello"); cout<<s.size()<<endl;        //OK cout<<"hello".size()<<endl;  //ERROR cout<<s+"world"<<endl;       //OK cout<<"hello"+"world"<<endl; //ERROR      strlen、sizeof與size()求字符串長度的區別   cout<<strlen("123")<<endl;   //返回 3 cout<<sizeof("123")<<endl;   //返回 4 string s = "123"; cout<<s.size()<<endl;        //返回 3     標准string庫中的getline函數返回時會丟棄換行符   const iterator與const_iterator的區別   vector<int>::const_iterator //不能改變指向的值,自身的值可以改變 const vector<int>::iterator //可以改變指向的值,自身的值不能改變 const vector<int>::const_iterator //自身的值和指向的值都是只讀的   任何改變vector長度的操作都會使已存在的迭代器失效。如:在調用push_back之後,就不能再信賴指向vector的迭代器了   vector<int> ivec; ivec.push_back(10); vector<int>::iterator it = ivec.begin(); cout<<*it<<endl; ivec.push_back(9); cout<<*it<<endl;      //迭代器已經失效     數組與指針   字符數組除了可以用花括號在定義時初始化外,還可以用字符串字面值初始化,但謹記字符串字面值包含一個額外的空字符   char c1[] = {'h','e','l','l','o'}; char c2[] = "hello"; cout<<sizeof(c1)/sizeof(char)<<endl;  //長度是5 cout<<sizeof(c2)/sizeof(char)<<endl;  //長度是6   一個數組不能用另一個數組初始化,也不能將一個數組賦值給另一個數組   int a[3] = {1,2,3}; int b[3][3] = {{1,2,3},{1,2,3},{1,2,3}}; //right int c[3][3] = {a,a,a};   //error   若指針保存0值,表明它不指向任何對象。但是把int型變量賦值給指針是非法的,盡管此int型變量的值可能為0   int a = 0; int *p1 = 0;   //right int *p2 = a;   //error     typedef string *pstring;  const pstring cstr;  cstr的類型是 string * const 還是 const string * ? 答:是string *const cstr,而非 const string *cstr。容易產生誤解的原因是const限定符既可以放在類型前也可以放在類型後,const pstring cstr等價於pstring const cstr。遇到此類問題時,把const放在類型之後來理解。   區分:int *ip[4] 和 int (*ip)[4] 第一個表示一個數組,元素是int指針 第二個表示一個指針,指向int數組,遇到此類問題時,由內向外讀。       運算符   除法/和求模% 若兩個操作數是正數,則除法的結果是正數,求模的結果也是正數 若兩個操作數是負數,則除法的結果是正數,求模的結果是負數 若只有一個操作數是負數,則除法和求模的結果取決於機器,除法可以確定結果是負數   邏輯與和邏輯或操作符總是先計算其左操作數,然後再計算其右操作數,只有在僅靠左操作數的值無法確定該邏輯表達式的結果時,才會求解其右操作數   區分 if(i<j<k) 和 if(i<j && j<k) 第一個i<j或者為0或者為1,只要k大於1,表達式就為true 第二個必須i<j且j<k表達式才為true   區分 if(val) 和 if(val == true) 第一個只要val非零則表達式為true,val為0則表達式為false 第二個只有val為1表達式為true,val非1則表達式為false   int val = 2; if(val==true){              //不會進入if   cout<<"val==true"<<endl; }   多個賦值操作符中,各對象必須具有相同的數據類型,或者具有可轉換為同一類型的數據類型。   int ival; int *pval; ival = pval = 0;  //error 盡管ival和pval都可以賦值為0 string s1,s2; s1 = s2 = "OK"    //ok   如果指針指向不是用new分配的內存地址,則在該指針上使用delete是不合法的。   通常編譯器不能斷定一個指針是否指向動態對象,因此盡管這樣做是錯誤的,但在大部分編譯器上仍能運行通過,但是會產生運行時錯誤。   整形提升   對於所有比int小的整形(char, signed char, unsigned char, short, unsigned short),如過該類型所有可能值都包含在int中,他們會被提升為int型,否則,他們將被提升為unsigned int。   對於包含signed和unsigned int型的表達式,表達式中的signed型整數會被轉換為unsigned型。   int i = -5; unsigned int ii = 1; cout<<(i>ii)<<endl;   //輸出1,非常有趣的結果 原因是int型的i轉換為unsigned int型 short i = -5; unsigned short ii = 1; cout<<(i>ii)<<endl;  //輸出0 比較時short和unsigned short都提升為int型

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved