小古銀的官方網站(完整教程):http://www.xiaoguyin.com/
C++入門教程視訊:https://www.bilibili.com/vide…
變數
前面簡單講解過變數,現在就再詳細講解變數。
先給出幾個關於變數的建議:
- 基本資料型別的變數要初始化。
- 避免使用全域性變數。
- 每個變數宣告時單獨一行。
- 變數名稱應該符合變數的用途。
基礎示例
#include <iostream> // std::cout std::endl
#include <string> // std::string
std::string global = "這是全域性變數"; // 全域性變數, 作用域是全域性, 即在程式結束是才會銷燬
int main(int argc, char *argv[]) // 函式引數也是變數, 作用域是該函式內部, 即函式以外就不存在
{
std::string text1 = "這是區域性變數"; // 區域性變數, 作用域是最近的左右大括號, 即作用域是主函式
// 在程式碼中加入左右大括號可以限制變數的作用域
{
std::string text2 = "這也是區域性變數"; // 作用域是最近的左右大括號, 即下一行以後它佔用的記憶體就會被銷燬而不存在
std::cout << text1 << std::endl << text2 << std::endl;
}
std::cout << text1 << std::endl;
std::cout << global << std::endl;
std::cout << argc << std::endl;
// 這個輸出的是記憶體中的地址
// 由於每次程式啟動都是由系統重新分配記憶體
// 所以每次輸出的記憶體地址都不會一樣
std::cout << argv << std::endl;
return 0;
}
輸出結果:
這是區域性變數
這也是區域性變數
這是區域性變數
這是全域性變數
1
034D6538
基礎講解
前面教程提到過std::string
宣告的變數用來儲存字串,如:
std::string text = "這是字串";
宣告變數的位置大致分為三種:
- 全域性變數:在所有函式之外宣告的變數。它的作用域是全域性,整個程式所有地方都可以使用這個變數,程式結束時才釋放變數的記憶體。
- 區域性變數:除全域性變數以外的都是區域性變數。它的作用域是離它最近的一對左右大括號{ }之間,在程式執行到},那麼,這個變數的記憶體就會釋放,換言之,在它的作用域以外的地方,這個變數是不存在的。
- 形式引數:形式引數是特殊的區域性變數,它在函式名後面的一對圓括號中定義。它的作用域就在這個函式內,在這個函式以外的地方,這個變數不存在。程式碼中的argc和argv就是形式引數。
基礎擴充
注意:
- 如果兩個不同作用域有著兩個變數,而這兩個變數名稱是一樣的,那麼它們並不是同一個變數。
- 如果在一個作用域中有一個子作用域,子作用域與外部作用域都含有相同名字的變數(如全域性變數和區域性變數),那麼,在子作用域使用的變數是子作用域的變數。
建議變數初始化的原因:基本資料型別的變數宣告之後,它會儲存一個不確定的數,為了防止程式使用這個不確定的數導致程式出現問題(其他資料型別則要看情況,如std::string
則不需要初始化)。
避免使用全域性變數的原因:上面注意中的第二條就是原因,防止寫程式時誤操作。如果為區域性變數起一個名字與全域性變數,當全域性變數多了,開發過程中就會思考區域性變數起名字的問題,會導致開發變慢和程式碼難讀的問題。
為注意中的兩點舉一個例子:
#include <iostream> // std::cout std::endl
#include <string> // std::string
std::string global = "這是全域性變數";
int main(void)
{
std::string global = "這個global並不是全域性變數";
std::cout << global << std::endl;
{
std::string text = "區域性變數1";
std::cout << text << std::endl;
}
{
std::string text = "區域性變數2";
std::cout << text << std::endl;
}
return 0;
}
輸出結果:
這個global並不是全域性變數
區域性變數1
區域性變數2
在編譯的過程中,應該會看到一個警告,說是區域性變數隱藏了全域性變數。那麼這個全域性變數global
在區域性變數global
的作用域(即主函式)裡都是不能使用的。這就是新手要注意的:不能忽視警告資訊。
const
既然有變數,那麼相對應的就應該有不變數。
有一些變數,初始化之後就並不想它再改變,那麼它就是不變數。然而,實際上這個變數儲存的值還是可以改變。為了防止以後不小心給這些不想被改變的變數賦值,所以出現了關鍵字const
。
const
就是為了禁止變數儲存的值改變而出現的。用const
宣告的變數,當試圖改變這個變數的值,那麼出現編譯錯誤。所以const
宣告的變數就是不變數。
由於const
宣告的變數,後面不能被改變,所以const
宣告的變數必須被初始化。
基礎示例
#include <iostream> // std::cout std::endl
int main(void)
{
const int a = 100; // 不變數a, 如果去掉賦值, 編譯就會報錯, 提示必須初始化
std::cout << a << std::endl;
// 如果去掉下面的註釋, 那麼編譯的時候會報錯, 說a是不能修改的
// a = 2333;
return 0;
}
輸出結果:
100
基礎講解
由於變數a
宣告的時候使用了const
,所以下面它儲存的值都不能發生變化。
建議:每個const
變數宣告時單獨一行。
注意:const
變數的注意事項跟變數的注意事項相同。
基礎擴充
像數字123
、字元`a`
等這些字面量,它們是不變的值,所以它們是常量。
上面程式碼中由於變數a
儲存的是字面量,而且儲存的值不會改變,所以變數a
也是常量。
constexpr
關鍵字constexpr
是更嚴格的const
,const
作用是不改變變數,而constexpr
變數儲存的值必須可以在編譯的時候求出來。這意味著constexpr
變數必須儲存字面量:
int a = 1;
constexpr int b = 2;
constexpr int c = b;
// 去掉下一行程式碼將會報錯
// constexpr int d = a;
由於變數a
的值在程式中可變,並不能在編譯期確定,所以constexpr int d = a;
將會報錯。而constexpr int b = 2;
,2是字面量,那麼constexpr
宣告的變數b
就可以在編譯期確定它的值,就是2,並且不會被改變。由於變數b
是constexpr
,所以constexpr int c = b;
也是成立的;編譯器在編譯期會轉化成constexpr int c = 2;
。
初始值
我們知道,變數宣告時就應該初始化,接下來,來看看比較有意思的初始值。
基本資料型別初始化時,除了指定明確的數值以外,還可以使用預設初始值:
基礎示例
#include <iostream>
int main(void)
{
int a = int();
float b = float();
unsigned long long c = unsigned long long();
std::cout << a << std::endl;
std::cout << b << std::endl;
std::cout << c << std::endl;
return 0;
}
輸出結果:
0
0
0
基礎講解
從程式碼中可以看出,基本資料型別的預設初始值就是基本資料型別後面加上()
,如int()
。而預設初始值的實際數值就是0。
當然,你也可以在括號內寫數值,如int a = int(5);
,那麼就等價於int a = 5;
。
補充知識(瞭解即可)
關鍵字constexpr
是從C++11起加入。