1 關(guān)鍵字inline :調(diào)用Inline函數(shù)直接嵌入代碼,,避免因為調(diào)用而造成的開銷,。 注意,,內(nèi)聯(lián)函數(shù)應(yīng)該放入頭文件中。 extern :使用時候,,也必須聲明,,應(yīng)用應(yīng)在cpp文件中,。 const : A.h中定義的全局變量int a;能被別的cpp文件訪問,只要extern int a; 如果不想被訪問,,則定義成const int a; &引用: 引用是一種復(fù)合類型,,必須用對象初始化,,是對象的別名。 int & i= 10;error int & i= j;right const &是指向const對象的引用,。 const int i= 10; const int & j= i;right int &k = i; error typedef 類型或結(jié)構(gòu) 別名 static :是靜態(tài)對象,。即使函數(shù)退出,該變量仍然未銷,,直到程序退出,。 2 系統(tǒng)函數(shù)atoi :const char*轉(zhuǎn)int形,window下可用 atol :const char*轉(zhuǎn)long形,,window下可用 sprintf : linux下可用這個函數(shù)進(jìn)行轉(zhuǎn)換成字符數(shù)組,,但是,不能轉(zhuǎn)成string類型,。 可先轉(zhuǎn)成char s[],,進(jìn)而轉(zhuǎn)成string。 ntohl ntohs htonl
memchr strchr查找char*中的某個字符位置 strstr 查找char*中的某個char*位置 memcmp 比較char* memcpy char*拷貝 memmove char*移動 memset char*按位設(shè)置字符
流輸入 #include stringstream os; int i=1001; string str; os << i << “.hello”; os >> str; //os.str();
strtok 分割字符串:char *strtok(char *s, const char *delim); 分解字符串為一組字符串,。s為要分解的字符串,,delim為分隔符字符串。
3 初級編程3.1網(wǎng)絡(luò)字節(jié)序?qū)R27 #pragma pack(push,1) 28 typedef struct JsonHeader 29 { 30 uint32_t m_len; 31 uint16_t m_cmd; 32 uint32_t m_seq; 33 }JSONHEADER; 34 #pragma pack(pop) 3.2 預(yù)處理#ifndef _HELLO_ #define _HELLO_ //頭文件,,變量,,函數(shù)聲明 #endif 3.3 函數(shù)返回值函數(shù)返回對象的引用,沒有復(fù)制返回值,。 禁止返回局部變量的引用,。 const string & fun(const string &s) { string s2 = s; return s2;//error,函數(shù)執(zhí)行完畢后釋放s2 return s; } 3.4 函數(shù)指針和回調(diào)函數(shù)函數(shù)指針是指向函數(shù)的指針變量。 因而“函數(shù)指針”本身首先應(yīng)是指針變量,,只不過該指針變量指向函數(shù),。這正如用指針變量可指向整型變量、字符型,、數(shù)組一樣,,這里是指向函數(shù),。如前所述,C在編譯時,,每一個函數(shù)都有一個入口地址,,該入口地址就是函數(shù)指針?biāo)赶虻牡刂贰S辛酥赶蚝瘮?shù)的指針變量后,,可用該指針變量調(diào)用函數(shù),,就如同用指針變量可引用其他類型變量一樣,在這些概念上是一致的,。函數(shù)指針有兩個用途:調(diào)用函數(shù)和做函數(shù)的參數(shù),。 int func(int x); int (*f) (int x); f=func; 賦值時函數(shù)func不帶括號,也不帶參數(shù),,由于func代表函數(shù)的首地址,,因此經(jīng)過賦值以后,指針f就指向函數(shù)func(x)的代碼的首地址 例子: //返回值是一個引用 const int & max(const int &x,const int &y) { return (x>y?x:y); }
const int & (*ptr)(const int &,const int & );
int fun_point_test() { int x = 1; int y = 2; ptr = max;//對指針賦初值 cout<<"max = "<<(*ptr)(x,y)<<endl; cout<<"max = "<<max(x,y)<<endl; return 0; } 3.5 值傳遞值傳遞:函數(shù)不會訪問當(dāng)前調(diào)用的實參,,函數(shù)處理的值是它本地的一個拷貝,,這些拷貝被保存在棧中,一旦函數(shù)退出,,它們就會消失,。參數(shù)實際值不會改變。 值傳遞不適合大型類對象作為參數(shù),,拷貝開銷太大,。 引用傳遞:別名,指向同一塊內(nèi)存空間,。 想用引用又不想改變其值,,可以定義成const A& 3.6 拷貝構(gòu)造函數(shù)當(dāng)類中有指針成員變量和new開辟新的空間時候,必須使用拷貝構(gòu)造函數(shù),。 A{private:int *p; public:A(const A&);p = new int[10];}
3.7虛函數(shù),、純虛函數(shù)、抽象類,、虛析構(gòu)函數(shù)虛函數(shù)定義在基類中,,實現(xiàn)也可以在基類中,如果子類沒有同名函數(shù),,則仍然用基類中的虛函數(shù),。 純虛函數(shù)定義在基類中,實現(xiàn)必須在子類中,,是一種多態(tài)的體現(xiàn),。 具有純虛函數(shù)的類稱抽象類,不能實例化對象,必須有子類繼承,,實現(xiàn)其純虛函數(shù),。 虛析構(gòu)函數(shù)不能隨便聲明,只有在class作為多態(tài)的基類時,,適合將基類的析構(gòu)函數(shù)聲明成虛析構(gòu)函數(shù),。
3.8鏈接庫靜態(tài)鏈接庫 生成靜態(tài)lib #ifdef _STATIC_LIB_H_ #define _STATIC_LIB_H_
#ifdef __cplusplus extern "C" { #endif int add(int a, int b);
int subtract(int a, int b);
#ifdef __cplusplus { #endif #endif -------------------------------------- #include"StaticLib.h"
int add(int a, int b){
return a+b;
}
int subtract(int a, int b){
return a-b;
}
使用 將.lib和.h拷到目錄下。 #include #include"StaticLib.h" #pragma comment(lib,"StaticLib.lib") int main (){ int a=3,b=4; int c=0; c=add(a,b); printf("%d+%d=%d",a,b,c ); c=subtract(a,b); printf("%d-%d=%d",a,b,c ); //return 0;
} 動態(tài)鏈接庫 一,,生成動態(tài)鏈接庫 //DynamicLib.h #ifndef _DYNAMIC_LIB_INCLUDE_H_ #define _DYNAMIC_LIB_INCLUDE_H_ #ifdef __cplusplus extern"C"{ #endif
_declspec(dllexport) int add(int a,int b); _declspec(dllexport) int sub(int a,int b);
#ifdef __cplusplus }; #endif
#endif ------------------------------------------------------ //DynamicLib.cpp #include "DynamicLib.h"
int add(int a,int b){ return a+b; } int sub(int a,int b){ return a-b; } --------------------------------------------------- 生存動態(tài)鏈接庫,,得到兩個文件如下: DynamicLib.dll DynamicLib.lib
使用動態(tài)鏈接庫 2.1隱式使用 #include "DynamicLib.h" #pragma comment(lib,"DynamicLib.lib") int main(){ int a=10; int b=20; int c=0; c = add(a,b); printf("%d+%d=%d\n",a,b,c); c = sub(a,b); printf("%d-%d=%d\n",a,b,c); return 0; } 2.2顯示使用 #include //#include "DynamicLib.h" #include //#pragma comment(lib,"DynamicLib.lib") typedef int(*pADD)(int a,int b); typedef int(*pSUB)(int a,int b); int main(){//顯示使用動態(tài)鏈接庫 HINSTANCE hModule = ::LoadLibrary("DynamicLib.dll"); //句柄 pADD add = (pADD)::GetProcAddress(hModule,"add"); pSUB sub = (pSUB)::GetProcAddress(hModule,"sub"); int a=10,b=20,c=0; c = add(a,b); printf("%d+%d=%d\n",a,b,c); c = sub(a,b); printf("%d-%d=%d\n",a,b,c);
::FreeLibrary(hModule); return 0; }
4 C++工程規(guī)范 1).h文件定義函數(shù)和變量 .cpp實現(xiàn) 2)文件名小寫全拼 類名首字母大寫pascal規(guī)則 3)盡可能用const定義變量和函數(shù) 4)必須進(jìn)行返回值判斷。 3.9 GDB
valgrind --leak-check=full ./ if(it->second) 171 { 172 if(it->second->vec145data.size() != 15) 173 { 174 cout <<"map145bacdata vec145data size = " << it->second->vec145data.size() <<endl; 175 assert(0);//程序強(qiáng)制在這個地方出core 176 } 177 } 3.10 STL1. 循環(huán)語句刪除map中的元素,,應(yīng)將it++放在刪除的地方 map145bacdata->erase(it++); it++不能放在for體里面,。 2. vector不完全排序 bool UDgreater ( DataInfo elem1, DataInfo elem2 ) return elem1.dzf > elem2.dzf; int sortsize(5); partial_sort(vecInfo.begin(), vecInfo.begin() + sortsize, vecInfo.end(), UDgreater);//不完全排序,stl中的方法 3. vector完美刪除
3.11 指針指針的應(yīng)用應(yīng)該注意,,在什么時候new出來的地方,一定要注意delete,,否則會造成內(nèi)存泄露,,程序崩潰。 可以用C++的delete釋放,,也可以用自己編寫的釋放內(nèi)存類釋放,。 特別是結(jié)構(gòu)體內(nèi)的指針釋放,應(yīng)該注意,。 4 高級編程4.1模板templatetemplate void ClearAndFreeMap(map *needfreemap) { typename map::iterator it; for(it = needfreemap->begin(); it != needfreemap->end(); it++) { if(it->second) { delete it->second; it->second = NULL; } } needfreemap->clear(); } 4.2 map結(jié)構(gòu)體key用法
5 代碼優(yōu)化5.1 變量(1) 變量在哪兒使用,才開始定義,,這點和C語言編程風(fēng)格不同,。 (2) 常量用const修飾。 (3) 靜態(tài)變量 s_ (4) 全局變量 g_ (5) 類成員變量 m_ 5.2 好的編程習(xí)慣(1) “,,”后面空一格,,賦值、比較等符號前后各空一格,。 (2) 函數(shù),、類等每個邏輯之間空一行。 (3) 賦值語句作為變量時,,應(yīng)將賦值語句加括號,。 (4) 指針必須在使用完后釋放。 (5) 重復(fù)代碼應(yīng)采取適當(dāng)?shù)姆椒?,將代碼合并,。 (6) 巧用os進(jìn)行任意類型的轉(zhuǎn)換。 #include os << “str”; os.str().c_str();//返回const char * (7) 類的成員變量聲明順序和類的構(gòu)造函數(shù)對成員變量的初始化順序應(yīng)保持一致。 (8) * & 等修飾符號 靠近數(shù)據(jù),。 int *i, j; (9) 注釋規(guī)范,。
(10)if——else—— if (condition) return x; return y; 改成 return (condition ? x : y); (11) 多重循環(huán),長循環(huán)在外層,,程序效率較高,。 (12) 斷言 assert 是僅在Debug 版本起作用的宏,它用于檢查“不應(yīng)該”發(fā)生的情況,。 在調(diào)試結(jié)束后,,可以通過在包含#include 的語句之前插入 #define NDEBUG 來禁用assert調(diào)用。 (13) 內(nèi)聯(lián)inline函數(shù)的聲明和定義都在一起,。內(nèi)聯(lián)是以代碼膨脹(復(fù)制)為代價,,僅僅省去了函數(shù)調(diào)用的開銷 (14) 把對象的初始化工作放在構(gòu)造函數(shù)中,把清除工作放在析構(gòu)函數(shù) 中,。當(dāng)對象被創(chuàng)建時,,構(gòu)造函數(shù)被自動執(zhí)行。當(dāng)對象消亡時,,析構(gòu)函數(shù)被自動執(zhí)行,。這 下就不用擔(dān)心忘了對象的初始化和清除工作。 (15) 拷貝構(gòu)造函數(shù)和賦值函數(shù),。 這是在創(chuàng)建類的對象的時候,,給對象初始化的兩種特殊的構(gòu)造函數(shù)。 string a(“hello”); string b(a); //拷貝構(gòu)造函數(shù) string c; c = a; //賦值函數(shù),,指向同一塊地址 (16) 引用傳遞的原則:對于非內(nèi)部數(shù)據(jù)類型的輸入?yún)?shù),,應(yīng)該將“值傳遞”的方式改為“const 引用傳遞”,目的是提高效率,。例如將void Func(A a) 改為void Func(const A &a),。對于內(nèi)部數(shù)據(jù)類型的輸入?yún)?shù),不要將“值傳遞”的方式改為“const 引用傳遞”,。 否則既達(dá)不到提高效率的目的,,又降低了函數(shù)的可理解性。例如void Func(int x) 不 應(yīng)該改為void Func(const int &x),。 用const 修飾函數(shù)的返回值 如果給以“指針傳遞”方式的函數(shù)返回值加const 修飾,,那么函數(shù)返回值(即指針)的內(nèi)容不能被修改,該返回值只能被賦給加const 修飾的同類型指針,。 |
|