一. 本篇要學習的內容和知識結構概覽
二. 知識點逐條分析
1. 使用函式過載
C++允許為同一個函式定義幾個版本, 從而使一個函式名具有多種功能, 這稱之為函式過載.
像這樣: 雖然函式名一樣, 但是引數列表不一樣, 一個求兩個整型引數的最大值, 一個求三個整型引數的最大值.
int getMax(int a, int b) {
if (a > b) {
return a;
} else {
return b;
}
}
int getMax(int a, int b, int c) {
if (a > b) {
if (a > c) {
return a;
} else {
return c;
}
} else {
if (b > c) {
return b;
} else {
return c;
}
}
}
複製程式碼
2. 新的基本資料型別及其注意事項
a. void是無型別識別符號, 只能宣告函式的返回值型別, 不能宣告變數
b. C++當中有bool型別, 而C中沒有
c. C++的常量分為符號常量, 浮點常量, 整數常量
像這樣:
我們可以通過螢幕輸出來檢視011, 11, 0x11各代表十進位制的多少
int a = 011; // 八進位制數
cout << a << endl; // 以十進位制格式輸出
int b = 11; // 十進位制數
cout << b << endl; // 以十進位制格式輸出
int c = 0x11; // 十六進位制
cout << c << endl; // 以十進位制格式輸出
複製程式碼
3. 動態分配記憶體
申請記憶體空間: new 型別名[size], 申請可以存size個該資料型別物件的儲存空間
釋放記憶體空間: delete 指標名;
像這樣:
int * p; // 宣告int型別指標
p = new int[5]; // 申請5個int型別資料的儲存空間
cout << p << endl; // 該記憶體空間的首地址
delete p; // 釋放記憶體空間
複製程式碼
4. 引用
為現有物件起個別名, 別名代表的記憶體空間與引用物件的記憶體空間是一樣的
引用的宣告方式: 資料型別(型別名) & 別名 = 物件名;
&的位置無關緊要
像這樣:
int c = 10;
int & d = c;
int& e = c;
int &f = c;
cout << c << endl;
cout << d << endl;
cout << e << endl;
cout << f << endl;複製程式碼
我們再進一步的使用它
int a = 5; // 定義int型別變數, 並賦值
cout << a << endl; // 輸出變數a的值: 5
cout << &a << endl; // 輸出變數a的地址: 0x7ffeefbff52c
int & b = a;
cout << b << endl; // 引用b的值: 5
cout << &b << endl; // 引用b的地址: 0x7ffeefbff52c複製程式碼
可以看到, 上下兩組輸出結果是一樣的, 也就是說引用b, 和變數a都是代表的同一塊記憶體地址
所以更改b的值, a的值也會變
b = 8;
cout << a << endl;
複製程式碼
注意: 引用, 就是給一塊已經存在的記憶體新增一個新的識別符號, 所以使用引用沒有分配新的記憶體空間, 所以可以通過引用來修改原來的物件, 但是不能有空引用, 它必須和一聲正確的儲存區域關聯
像這樣: 是錯誤的
int & b;
// 編譯器提示資訊: Declaration of reference variable 'b' requires an initializer, 變數b需要一個初始化器
引用的作用
a. 引用用於函式的參數列, 不產生臨時物件, 提高安全性和執行效率
void swap(int & a, int & b) {
int temp = a;
a = b;
b = temp;
}
int a = 5;
int b = 10;
cout << "交換前 " << "a的值:" << a << " b的值:" << b << endl;
swap(a, b);
cout << "交換後 " << "a的值:" << a << " b的值:" << b << endl;
複製程式碼
b. 引用用於函式返回值 用到的時候很少, 因為不安全, 你可能問訪問到一個已經被釋放的物件
引用可以這麼使用
int a = 5;
int & b = a; // 宣告引用
int * p = &a; // 宣告指向變數的指標
int * q = &b; // 宣告指向引用的指標
int * & r = p; // 宣告指標對指標的引用 (p, r是指標, 等號左邊 * 代表宣告的r是指標, &代表宣告的r是引用)複製程式碼
但是不能這麼使用
int & & s = a; // 不能宣告引用的引用
複製程式碼
指標和引用的區別和聯絡
聯絡: 它們都會對記憶體地址上存在的變數進行修改, 但引用不佔用新的地址, 節省開銷
區別: 指標是低階的直接操作記憶體地址的機制, 可由整型數強制型別轉換得到, 功能強大, 但是容易出錯, 引用是較高階的封裝了指標的特性, 不直接操作記憶體地址, 不可強制型別轉換得到, 安全性高
5. 對指標使用const限定符
a. 指向常量的指標
int a = 5;
int b = 8;
const int * p = &a; // 指向常量的指標, 也就是"*p="不成立, 也就是不能通過指標p修改指向的記憶體地址中的值, 但是p的值可以更改
*p = 10; // 錯誤
p = &b; // 正確
複製程式碼
int a = 5;
int b = 8;
int * const p = &a; // 常量指標, 也就是"p="不成立, 也就是p的值不能更改, 但是是它所指向的記憶體地址中的值可以修改
*p = 10; // 正確
p = &b; // 錯誤
複製程式碼
c. 指向常量的常量指標
int a = 5;
int b = 8;
const int * const p = &a; // 指向常量的的常量指標, 既不可以通過p修改它所指向的記憶體地址中的值, 也不可更改p的值
*p = 10; // 錯誤
p = &b; // 錯誤複製程式碼
6. 泛型演算法應用於普通陣列
// 定義陣列
int a[] = {3, 2, 1, 5, 4};
int b[5] = {};
// 陣列反轉
// reverse(a, a + 5);
// 升冪排序
// sort(a, a + 5);
// 降冪排序
// sort (a, a+5, greater<int>());
// 複製陣列內容
// copy(a, a + 5, b);
// 逆向複製陣列a中的內容到陣列b
// reverse_copy(a, a + 5, b);
// 檢索
// int * p = find(a, a + 5, 5);
// cout << p << endl;
// cout << a + 5 << endl;
// if (p == a + 5) {
// cout << "沒有值為5的陣列元素" << endl;
// } else {
// cout << "有值為5的陣列元素" << endl;
// }
// 正向輸出
copy(a, a + 5, ostream_iterator<int>(cout, "數字 "));
cout << endl;
// 逆向輸出
reverse_copy(a, a + 5, ostream_iterator<int>(cout, "數字 "));
for (int i = 0; i < 5; i++) {
cout << a[i] << " ";
}
cout << endl;
for (int i = 0; i < 5; i++) {
cout << b[i] << " ";
}
cout << endl;複製程式碼
7. 程式的編輯, 編譯, 連線, 執行的基本概念
使用編輯器編輯一個C++源程式, 也就是原始檔, 副檔名為.cpp, 像這樣: Hello.cpp;
使用C++編譯器對這個源程式進行編譯, 產生目標檔案, 副檔名為.obj, 像這樣: Hello.obj;
使用連線程式, 將目標檔案與系統庫連線, 產生可執行檔案, 副檔名為.exe, 你這樣: Hello.exe
任何時候我們都不要忘記語言只是我們解決問題的工具, 思想才是我們解決問題的本質, 技術不深, 我們可以去查, 去練習, 而思想只有慢慢的去陪養, 去思考, 去總結!