字面常數儲存於記憶體,現在的問題是若要將數值儲存在記憶體,並在稍後取回使用,該如何進行?
變數(Variable)提供一個有名稱的記憶體儲存空間,變數可包含的資訊包含變數資料型態、變數記憶體位址與變數儲存值;C++ 開發者也常用物件(object)這個名稱來表示變數,因為物件對 C++ 開發者來說,不只是表示類別實例之類的東西,而是代表著一塊記憶體區域,可能含有型態與值等資訊。
在 C++ 中要使用變數,必須先宣告變數名稱與資料型態,例如:
int age; // 宣告一個整數變數
double money; // 宣告一個倍精度浮點數變數
C++ 使用 int
、float
、double
、char
、bool
等宣告變數名稱與型態,變數命名時不可以使用數字作為開頭,也不可以使用一些特殊字元,像是 *&^% 之類的字元,變數名稱不可以與 C++ 內定的關鍵字同名,例如 int
、float
、class
等等。
在 C++ 宣告變數,會配置一塊記憶體空間,空間長度依宣告時的資料型態而定,如果在函式外宣告變數,變數會預設為對應型態的零值,若是在函式中宣告變數,被配置的這塊空間中原先可能就有資料,也因此變數在宣告後的值是不可預期的,應該在在變數宣告後初始其值,可以使用「指定運算子」(Assignment operator)=
來指定變數的值,例如:
int ageForStudent = 0;
double scoreForStudent = 0.0;
char levelForStudent = 'A';
上例中三個變數分別被初始為 0
、0.0
與 'A'
,還可以使用隱喻的方式來宣告變數並指定初值,例如:
int ageForStudent(0);
double scoreForStudent(0.0);
char levelForStudent('A');
這兩種宣告方式在宣告變數的時候,同時指定變數的儲存值,字元在指定時需使用單引數 ''
包括,在宣告並指定變數值之後,可以使用變數名稱來取得其所儲存的值,下面這個程式是個簡單的示範:
#include <iostream>
using namespace std;
int main() {
int ageForStudent;
double scoreForStudent;
char levelForStudent;
cout << "\n年級\t得分\t等級";
cout << "\n" << ageForStudent
<< "\t" << scoreForStudent
<< "\t" << levelForStudent
<< "\n";
ageForStudent = 5;
scoreForStudent = 80.0;
levelForStudent = 'B';
cout << "\n年級\t得分\t等級";
cout << "\n" << ageForStudent
<< "\t" << scoreForStudent
<< "\t" << levelForStudent
<< "\n";
return 0;
}
這個程式先宣告變數,但沒有初始其值,第一次顯示時會出現不可預期的資料,而在指定變數的值之後,顯示變數值時就會出現指定的資料了,執行結果如下所示:
年級 得分 等級
4200459 1.55553e-306
年級 得分 等級
5 80 B
也可以在使用宣告變數後,使用以下的建構子(Constructor)方式將變數的值初始為各型態的零值:
int ageForStudent = int();
double scoreForStudent = double();
char levelForStudent = char();
在 C++ 11 中,增加了清單初始化(list initialization),其目的在統一初始化的方式,對於基本型態,也可以使用同一種風格來初始化。
int ageForStudent{0};
double scoreForStudent{0.0};
char levelForStudent{'A'};
這種初始化還有個特性,{}
中的值若指定給變數時,有可能造成精度遺失的話,編譯器會提出警訊。例如:
double pi = 3.14159;
int x = {pi}; // warning: narrowing conversion of 'pi' from 'double' to 'int' inside { }
如果如下撰寫,預設是不會提出警訊的:
double pi = 3.14159;
int x = pi;
這是因為型態發生了隱式轉換(implicit conversion),pi
的小數會被截去,整數部份被指定給 x
,若在這種情況下,也想要編譯器提出警訊,編譯時可以加上 -Wconversion
引數。
可以在宣告變數時使用 const
關鍵字來限定,如果程式中有其他程式碼試圖改變這個變數,編譯器會檢查出這個錯誤,例如:
const double PI = 3.14159;
PI = 3.14;
這一段程式碼中的 MAX
變數我們使用 const
來限定,所以它在指定為 10 之後,就不可以再指定值給它,所以第二次指定會被編譯器指出錯誤,在 g++ 編譯器時會出現這樣的錯誤訊息:
error: assignment of read-only variable 'PI'
使用 const
來限定的變數,目的通常就是不希望其它程式碼來變動值,例如圓周率 PI 的指定。
從 C++ 11 開始,可以使用 constexpr
請編譯器驗證常數初始時是在編譯時期決定,例如:
constexpr int A = 10;
constexpr int B = sizeof(10);
constexpr int C = sizeof(B);
constexpr int D = rand(); // error: call to non-'constexpr' function 'int rand()'
rand
傳回隨機亂數,因此 D
的實際值要在執行時期才能決定,而非編譯時期,因此發生錯誤;constexpr
的價值在於,在重重的運算式或函式呼叫下,編譯時期常數有時很難一眼看出,這時加上 constexpr
請編譯器來進行檢驗就方便多了。
如果要宣告無號整數變數,可以加上 unsigned
關鍵字,例如:
unsigned int i ;
bool
型態的變數雖然也可視為整數型態,但不能在宣告變數時加上 unsigned
來修飾。
從 C++ 11 開始,若變數宣告後有明確地初始化,可以使用 auto
讓編譯器推斷變數型態,例如:
int ageForStudent = 5;
double scoreForStudent = 80.0;
char levelForStudent = 'B';
可以改為:
auto ageForStudent = 5;
auto scoreForStudent = 80.0;
auto levelForStudent = 'B';
只用 auto
卻沒有初始,會發生編譯錯誤:
auto ageForStudent; // error: declaration of 'auto ageForStudent' has no initializer