C++ 純編譯型語言,支持面向對象。html
變量 | bool | char | short | int | void* | long | float | double |
---|---|---|---|---|---|---|---|---|
內存 | 1 | 1 | 2 | 4 | 4 | 4/8 | 4 | 8 |
// C++ 存在基本的 bool 類型,不像 C,啥都沒有 // 這兩條語句是基本類似的 if(1){ cout<<true; } if((bool)1){ cout<<true; } /* * C/C++ bool 自動轉化規則 * 0/NULL --> false * number/(void*) --> true */
cin/cout 自己是一種流對象。ios
// 流對象支持指針或標準變量 cout<<"hello world"<<"!\n"<<endl; cin<<b;
#define //宏變量 static int a; //靜態變量 extern int b; //引入外部變量 register int c; //寄存器變量 auto int e; //默認塊變量 const int d; //只讀變量 volatile int f; //對變量施加內存屏障,訪問控制不走任何緩存 restrict int g; //當前對象只有這一個引用可訪問,其餘全部引用皆無效 mutable //存儲類,對象相關 thread_local //存儲類,線程相關
/* 1. 算術運算符 2. 關係運算符 3. 邏輯運算符 ! && || 邏輯運算會自動短路 4. 位運算符 5. 賦值運算符 6. 其餘運算符 new : . >> << 等新增運算符。 */
while(){} for(){} // for 第一次也會執行判斷 do{}while(); switch(){case: break; case: continue;} if(){} if(){}else{} Exp ? Exp : Exp ; //簡化條件公式
// 函數定義沒啥好說的 void def(int a,int b){ count<<a<<b<<endl; } // 函數參數默認值,必須知足最右參數默認原則 void def(int a,int b=1,int c=2){ cout<<a<,b<<c<<a+b+c<<endl; } // def(0) def(0,1) def(0,1,2) 均可調用原始方法 // Lambda 函數表達式,這個語法糖好他媽醜 [capture](params)->{} // 示例 [](int x,int y)->{return x+y;} // 內聯函數,僅在最終須要時展開執行 inline int show(int a){ return a*10; } // lambda inline 函數儘可能只保留簡單功能,邏輯不宜過於複雜
// 數組 int a[10][10]; // 結構體 typedef struct List{ //... }list; // 位域結構體 typedef struct Step{ //... }step; // 共用體 typedef union Buffer{ //... }buffer; // 枚舉 // 可直接輸出,不可直接輸入,由於枚舉值是標識符常量 typedef enum Socre{ //... }score;
// 值傳遞,copy副本 // 沒法修改原始參數 void show(int val){ cout<<val++<<endl; } // 址傳遞,地址副本 // 可修改原始指針空間的值,以及指針 void show(int* val){ cout<<(*val)++<<endl; } // 引用傳遞,引用副本 // 可修改原始參數 void show(int& val){ cout<<val++<<endl; }
// C++ 字符串類 #include<cstring> string str = "hello world"; // 字符串長度 int len = str.size(); cout<<"hello"<<" world"<<endl; string str = str.substr(0,str.size()); str = str +str; string a = "abc"; string b = "adc"; // 比較兩個 string 對象時可用,基本 邏輯運算符 cout<<(a == b)<<endl; // 1 0 // 比較字符串對象與字符串時 cout<<a.compare("abc")<<endl;
// 至關於stdlib.h #include<iostream> // 數學方法函數 #include<cmath> // 時間函數相關 #include<ctime> // 不知道什麼庫 #include<cstdlib> // 10位時間戳 cout<<time(NULL); // 設置隨機種子爲當前 10位時間戳 srand((unsigned)time(NULL)); cout<<rand(); floor(3.6); -> int 3; floor(-3.6); -> int -4; ceil(3.6); -> int 4; ceil(-3.6); -> int -3; round(); // 精度 log(); // ln() log10(); // log10
# include<iostream> // 標準輸出流,默認屏幕 cout<<"hello world"<<endl; int a,b; // 標準輸入流,一次可執行多個 cin>>a>>b; // 標準錯誤流,默認屏幕,會當即輸出到屏幕 cerr<<"error"<<endl; // 標準日誌流,默認屏幕,存在緩衝區,緩衝區滿了則刷新一次 clog<<"log" // C++ 標準文件庫,能夠直接用 C 的標準文件庫 #include<fstream>
/* C 中的變量地址,能夠拿出來,也能夠利用地址強制指針化 C++ 中的變量地址,僅是可讀的,可是拿不出來,更安全,但卻少太多靈活性 */ // C int i = 100; int ad = &i; // 這裏能夠直接取到變量的實際內存地址 // C++ int i = 100; int ad = &i; // C++ 把這一步閹割了,&i 是可讀的,但沒法賦值於其餘變量 // C++ 引用,別名 int i = 100; int& j = i; // 此時 i j 僅表明一個變量,別名系統 int* p = &j; // i j 均可以取到指定的地址
throw try-catch。
C++ 異常處理與 Java 很是類似。
http://www.javashuo.com/article/p-rhrpvurf-bq.htmlc++
// 異常頭文件 #include<exception> // try-catch 語句塊 try{ if(true){ // 主動拋異常 throw 10; } // 捕獲異常 }catch(int e){ cout<<i<<endl; } cout<<"hello world"<<endl; // 自定義異常類型 class MyException:public exception{ virtual const char* what() const throw(){ return "MyException pass!"; } }myexception; // 別名? c++ 搞得好亂
int* p = NULL; // C++ new-delete 內存管瘤 p = new int; delete p; // C malloc-free 內存管理 p = (int*)malloc(sizeof(int)); free(p); // C++ new 申請一個對象空間,delete 釋放一個對象空間 // C malloc 申請指定大小的空間,free 釋放指針指向的空間
C++ namespace 搞的有點垃圾。不如 Java 靈活。數組
// 自定義命名空間 namespace first{ void show(){ cout<<"first-show"<<endl; } } // 使用 first.show() 方法 first::show() // 加載命名空間,內部成員可直接使用,必須知足過程式結構 using namespace first; // 可直接使用 show(); // 命名空間可嵌套定義,感受做用不大 namespace second{ namespace sec{ int i = 100; } } // 使用嵌套內部成員 second::sec::i;
C++ 模板系列,就是 Java 的泛型。
C++ 泛型類雙邊必須都存在類型的定義,Java僅須要一邊的。緩存
// 泛型-函數 template <typename T> void show(T param){ cout<<param<<endl; } // 泛型-類 template <class T> class Exp{ T p; public: show(){ cout<<this->p<<endl; } } // 使用泛型類 Exp<int>(1000).show(); Exp<int> p = Exp<int>(1000); p.show();
$關鍵點$ | $解決方法$ |
---|---|
指針定義 | 指針定義完成後,指向隨機棧地址;需初始化null |
指針釋放 | 除非還存在指向這片內存的指針,不然必須釋放堆內存 |
內存 | 任何地方,堆內存只能主動申請,主動釋放 |
內存指針 | 儘可能不要多指針指向同一片內存,易出現異常 |
內存申請 | 某些場景下,需判斷內存是否申請成功 |
內存釋放 | 內存被釋放後,指針依然可強制訪問,需設指針爲null |
函數參數 | 某些場景下,參數須要判斷null |
函數返回 | 函數僅能返回主動申請內存的指針,局部變量值 |
內存嵌套 | 嵌套的結構只能從最內層向外層遞歸釋放 |
內存數組 | 數組內使用堆內存還好,主要是當心下標越界問題 |
內存結構體 | 內部存在遞歸關係時,須要謹慎使用堆內存 |
class Exp{ int x; int y; // 靜態,類級別變量,但依然受限於權限控制符 static int sta; // 只讀,初始化對象,或定義時即完成初始化 const int con = 100; // 引用,初始化對象時,或定義時即完成初始化 int &y = x; // this 可訪問對象級別的全部成員 // this 沒法訪問類級別成員,static 靜態成員 Exp.sta sta 便可訪問 public: // 預約義方法,參數定義有兩種 int show(int x,int y); show(int); }; // class 結尾必須加 ;用以結束語句塊 // 實現預約義的具體方法 Exp::show(int x,int y){ return x+y; } Exp::show(int param){ cout<<param<<endl; } /* C++ 繼承特性,private成員沒法被繼承,支持多重繼承 public 繼承父類 public->public,protected->protected protected 繼承父類 public/protected -> protected private 繼承父類 public/protected -> private vittual 虛擬繼承 What Fuck! */
// 成員訪問控制 class Exp{ public: // 類-友元,子類,類外部 protected: // 類-友元,子類 private: // 類-友元 }; // 默認成員訪問控制 class Exp{ // 全部成員默認 private // 成員變量,默認私有 int x; // 成員函數,默認私有 void show(){ cout<<"hello world"<<endl; } };
// 友元,單向特性,擁有當前類的全部訪問權限 class Exp{ int x; // 此處申明指定類, 爲本類的友元類 friend class demo; // 此處申明指定函數,爲本類的友元函數 friend void show(Exp); } // 友元類 class Demo{...} // 友元方法 void show(Exp exp){ // 可直接訪問私有成員 cout<<exp.x<<endl; }
class Exp{ int x; public: // 構造函數,建立對象時執行 Exp(int x){ this->x = x; } // 基於重載特性,深拷貝函數 Exp(const Exp obj){ this->x = obj.x; } // 析構函數 ~Exp(){ // 釋放對象內存時執行 } /* 類繼承時 構造函數:父類執行,子類再執行 析構函數:子類執行,父類再執行 */ }
// 重載,函數同名但參數不一樣,則視爲不一樣函數 class Exp{ int x; public: Exp(int x){ this->x = x; } // C++ 支持,函數重名, void show(){ cout<<"hello world"<<endl; } void show(int params){ cout<<params<<ednl; } // 另外一種,運算符重載 =,賦予運算符特殊功能 Exp operator=(const Box& b){ //... return null; } }
// 子類可覆蓋父類中同名成員(包括變量,函數) class Exp{ public: void show(){ cout<<"Class Exp"<<endl; } }; class Demo:public Exp{ public: void show(){ cout<<"Class Demo"<<endl; } }; Exp().show(); Demo().show();
// 結構體方式建立對象,不推薦使用 Exp exp(1,2,3); // 默認內存管理 // 標準對象建立方式,非堆內存對象,推薦使用 Exp exp = Exp(1,2,3); // 默認內存管理 // 標準對象建立方式,堆內存對象,推薦使用 Exp* exp = new Exp(1,2,3); // 主動內存管理,new delete 管理對象內存 // 對象引用複製 Exp& ex = exp; // 對象指針複製,不推薦使用,多指針指向一個對象,內存管理很是麻煩 Exp* = &exp; // 標準對象訪問模式 exp.show(); // 指針對象訪問模型 exp->show(); // 快捷方式 Exp(1,2,3).show(); new Exp(1,2,3)->show();
C++ | Java | |
---|---|---|
類 | static 控制 |
static 控制 |
權限 | 3P原則,友元 | 3P原則 |
構造 | 構造析構,深拷貝 | 構造,GC回收,深拷貝,clone接口 |
繼承 | n,3P原則,都成爲子類的成員 | 1,public,子類與父類嚴格區分 |
覆蓋 | 子類可覆蓋父類的變量、函數 | 子類可覆蓋父類的函數 |
重載 | 重載函數,運算符重載 | 重載函數 |
對象 | 引用、指針,可快捷化 | 引用,可快捷化 |
virtual
所修飾的抽象方法。virtual
所修飾的抽象方法。class Exp{ public: // 純虛函數,就是Java中的抽象方法 virtual void show() = 0; }; class Demo:public Exp{ public: // 子類實現父類的抽象方法 void show(){ cout<<"hello world"<<endl; } }; // C++ 的抽象類:存在一個以上的純虛函數 // C++ 的接口類:內部僅存在純虛函數 // C++ 抽象系列與 Java 系列沒什麼差異
#include<vector> // 本質上就是一個數組,但支持動態擴容 // 開始時,申請一塊內存,擴容時釋放原內存,申請新內存便可 vector<int> arr = {1,2,3,4,5,6}; vector<int> arr(10,0); cout<<arr[0]<<arr[5]<<endl; arr.push_back(10); arr.pop_back(); arr.size(); stack<int> sta; sta.push(1); sta.pop(); unordered_set<string> set; set.insert("hello world!");
#include<deque> // 本質上就是一個雙端隊列,但其隊列頭、尾的插入刪除很是塊。
#include<list> // 雙向鏈表,插入、刪除快,隨機訪問比較慢。
#include<map> // 映射集合 key:value,內部自建一個紅黑樹
#include<set> // 集合,不容許重複,內部自建紅黑樹