目錄
1. 尾碼名... 1
2. include 預先處理指示符... 1
3. 條件指示符 #ifndef #indef. 2
4. 編譯器自動定義預先處理名字... 2
5. assert. 2
6. 標準錯誤... 3
7. 動態記憶體... 3
8. 內嵌函式 inline. 3
9. 引用與指標... 4
10. 異常處理... 5
11. 命名空間Namespace. 5
12. 常量... 6
13. C++關鍵字... 6
14. 變數初始化... 7
15. \0的理解... 8
16. const 指標的理解... 8
17. bool類型... 8
18. enum類型... 8
19. 數組... 9
20. vector類型... 9
21. pair類型... 9
1. 尾碼名
C++來源程式檔案尾碼名在不同產品中是不同的。
在Unix系統中,text.c 習慣上被當作C++來源程式檔案
C++標頭檔尾碼名在不同產品也是不同的。
標準C++標頭檔,是沒有尾碼名
2. include 預先處理指示符
preprocessor include directive
<> : 表明檔案是一個工程或者標準標頭檔
“” : 使用者提供的標頭檔,會首先在工程中尋找
3. 條件指示符 #ifndef #indef
#ifndef SOME_STRING#define SOME_STRING#else//some code#endif
4. 編譯器自動定義預先處理名字
編譯C++程式,編譯器會自動定義預先處理名字:__cplusplus
編譯C程式,編譯器會自動定義預先處理名字:__STDC__
__LINE__: 記錄檔案已經被編譯的行數
__FILE__: 正在編譯的檔案的名字
__TIME__: 當前被編譯檔案的編譯時間 hh:mm:ss
__DATE__: 當前被編譯檔案的編譯日期 Oct 5 2011
5. assert
assert() 是C語言標準庫中提供的一個通用前置處理器宏。
#include <assert.h>
在C++ 中 #include <cassert> (這是通用的轉化準則,去掉.h 首碼c)
#include <cassert>using namespace std;//這句是必須的,不然,assert仍然不可用
圖 1 系統先行編譯名字
6. 標準錯誤
cerr
cerr << "This is my error" << endl;
7. 動態記憶體
動態對象,也就是new出來的對象,沒有名字,我們通過指標間接的對它進行操作。
8. 內嵌函式 inline
將函數定義為內嵌函式有兩種方法:對與全域函數,只要在該函式宣告或定義時在前面加上關鍵詞inline就可以了;對於類的成員函數,當函數的實現在類體內部時,該函數就被預設為inline函數,當函數的實現在類體外部時,只需像全域函數一樣加上關鍵詞inline就可以了。
最後一點要注意的是,即使你把一個函式宣告或定義成了inline函數,也不能保證該函數一定能被編譯器當作內嵌函式來處理,只能說是建議當作內嵌函式來處理,例如當你的函數體很大,編譯器就基本不會把它當作內嵌函式來處理,這會因為頻繁調用該函數而導致程式碼體積的極速膨脹,在記憶體較小的機器中,會影響指令高速緩衝裝置的擊中率。
圖 2 正確的inline
setA自動會被認為是inline函數
如果在CPP中實現get2A,按照的做法,編譯報錯。
宏定義:前置處理器處理
inline:編譯器處理
9. 引用與指標
i. 指標指向一塊記憶體,它的內容是所指記憶體的地址;引用是某塊記憶體的別名。
ii. 指標是一個實體,而引用僅是個別名;
iii. 引用使用時無需解引用(*),指標需要解引用;
iv. 引用只能在定義時被初始化一次,之後不可變;指標可變;
v. 引用不可為空,指標可以為空白;
vi. “sizeof 引用”得到的是所指向的變數(對象)的大小,而“sizeof 指標”得到的是指標本身(所指向的變數或對象的地址)的大小;
typeid(T) == typeid(T&) 恒為真,sizeof(T) == sizeof(T&) 恒為真,
但是當引用作為成員時,其佔用空間與指標相同(沒找到標準的規定)。
vii. 指標和引用的自增(++)運算意義不一樣;
圖 3 輸出結果為4
圖 4 引用與指標定義
圖 5 不用類型轉換的引用
由圖4可知:如果不將b定義成const,那麼當b發生變化時,並不會影響a的值,那就不再是引用的的概念了。當定義成const,b是唯讀,b仍然相當儲存了a的地址,還是引用。
10. 異常處理
void fun() throw(int,string){…}
11. 命名空間Namespace
圖 6 命名空間
問題:如何在一個工程中建立多個名稱相同的類,放在不同的Namespace?
別名:Namespace newName = oldName;
圖 7 命名空間別名
12. 常量
C++ 語言可以用const來定義常量,也可以用 #define來定義常量。但是前者比後者有更多的優點:
(1) const常量有資料類型,而宏常量沒有資料類型。編譯器可以對前者進行型別安全檢查。而對後者只進行字元替換,沒有型別安全檢查,並且在字元替換
可能會產生意料不到的錯誤(邊際效應)。
(2) 有些整合化的調試工具可以對const常量進行調試,但是不能對宏常量進行調試。
【規則】在C++ 程式中只使用const常量而不使用宏常量,即const常量完全取代宏常量。
圖 8 常量
13. C++關鍵字
圖 9 C++關鍵字
14. 變數初始化
對於int、double:
全域變數,編譯器賦初始值0。
局部變數,需要手動賦初始值。(new出來的變數也是一樣)
對於char:
全域和局部都是賦0(ASCII碼)
圖 10 變數初始值
15. \0的理解
const char* p = “Hello world”;
最後一位是\0,所以
while(*p++)//++的優先順序大於*
:先把指標後移,然後取出其中的內容
:當字串結束時,會有一個\0,while條件即為false
16. const 指標的理解
緊跟在const關鍵字後面的就是不能變動的。
const char* str = “Hello Everyone!”;
表示char*是不能變動的,即str指標所指向的記憶體塊的內容不能變,即”Hello Everyone!”不能變,但是str本身可以變,它可以指向另一塊記憶體區
(如
char* str1 = “Hello World”;str = str1; //雖然這樣文法上是正確的, 但"Hello Everyone!”這塊記憶體塊就沒有指標指向它了,成了垃圾。//str[0] = ‘a’; //錯誤,記憶體塊的內容不能變
)
char* const str = “Hello Everyone!”;
表示str是不能變動的,即str指標所儲存的地址不能變,只能一直指向某個固定的記憶體塊,但是這個記憶體塊本身的內容可以改。但是str指標所指向的記憶體塊的內容可以變。
(如
str[0] = ‘0’;//正確char* str1 = “Hello World”;//str = str1;//錯誤,str儲存的地址不能變,所以它不能再指向另一個記憶體塊。
)
17. bool類型
1) 為什麼要使用內建bool類型,而不是自己通過typedef、enum等類比出來的bool類型?
l 程式可讀性好!
l 給編譯器最佳化代碼的機會。
內建bool類型一般均為 1 個位元組。
有些CPU將bool類型最佳化成儲存空間的某個位
2) C語言中的bool類型
18. enum類型
1) 一個元素只能定義在一種enum中,否則報錯
2) 沒有++操作
WeekDay day = Tuesday;day++;//Error,No Operator ++ for day
3) 不能直接賦整型值
WeekDay day;day = 1;//Error,Cannot Convert int to enum
4) 傳回值是索引值
WeekDay day = Monday;cout << day << endl; //結果是0
5) 後一個元素的預設索引值總是前一個元素的索引值+1
enum WeekDay{Monday=1,Tuesday,Wednesday=1,Thursday,Friday,Saturday=9,Sunday};
則各元素依次的索引值分別是:1,2,1,2,3,9,10
19. 數組
1) C++編譯器不對數組下表進行越界檢查
2) 數組之間不能直接賦值
int a[4] = {1,2,3,4};//int b[4] = a;//Error
20. vector類型
建議使用vector代替array,除非特殊情況必須使用array。
/************************************************************************************************ * 名 稱: main.cpp * 功 能:學習C++ Premier 的筆記之Vector * 描 述:無 * 作 者:JarvisChu * 時 間:2011-7-3 建立 ;7-4 修改; *************************************************************************************************/#include <iostream>#include <vector>#include <iterator>using namespace std;int main(){ //數組習慣用法 vector<int> arrNum(10); //定義一個初始大小為10的vector,預設初始值全為0 arrNum[0] = 10; arrNum[1] = 11; cout<<arrNum[0]<<endl; //輸出10 cout<<arrNum[3]<<endl; //輸出0 cout<<arrNum[10]<<endl; //輸出一個隨機的數 cout<<"------------華麗的分割線------------"<<endl; //STL習慣用法 vector<int> stlNum; stlNum.push_back(10); stlNum.push_back(11); stlNum.push_back(12); cout<<stlNum.at(0)<<endl; cout<<stlNum.at(1)<<endl; //cout<<stlNum.at(3)<<endl;//會拋出一個異常, cout<<"------------華麗的分割線------------"<<endl; vector<int> stlNum_1 = stlNum; //直接賦值初始化 cout<<stlNum_1.at(0)<<endl; cout<<"------------華麗的分割線------------"<<endl; vector<int>::iterator it; //使用迭代器遍曆vector for(it = stlNum.begin(); it != stlNum.end();it++){ cout<<*it<<endl; } return 0;}
21. pair類型
在單個對象內部把兩個類型相同或不同的值關聯起來。
/************************************************************************************************ * 名 稱: main.cpp * 功 能:學習C++ Premier 的筆記之pair * 描 述:無 * 作 者:JarvisChu * 時 間:2011-7-4 建立 *************************************************************************************************/#include <iostream>#include <utility>using namespace std;typedef pair<string,int> PERSON;int main(){ PERSON me("Jarvis",21); cout<<me.first<<endl<<me.second<<endl; return 0;}