C++Primer學習——第2章 變數和基本型別
變數和基本型別
文章目錄
C++ 算術型別
型別 | 含義 | 最小尺寸 |
---|---|---|
bool | 布林型別 | 未定義 |
char | 字元 | 8位 |
wchar_t | 寬字元 | 16位 |
char16_t | Unicode字元 | 16位 |
char32_t | Unicode字元 | 32位 |
short | 短整型 | 16位 |
int | 整型 | 16位 |
long | 長整型 | 32位 |
long long | 長長整型 | 64位 |
float | 單精度浮點數 | 6位有效數字 |
double | 雙精度浮點數 | 10位有效數字 |
long double | 擴充套件精度浮點數 | 10位有效數字 |
w_chart型別用於確保可以存放機器最大擴充套件字符集中的任意一個字元。
型別char16_t和char32_T為Unicode字符集服務。
內建型別的機器實現
可定址的最小記憶體塊被稱為“位元組(byte)”,儲存的基本單元被稱為“字(word)”
把負數轉換成無符號數類似於直接給無符號數賦一個負值,結果等於這個負數加上無符號數的模。
切勿混用帶符號型別和無符號型別
如果表示式裡既有帶符號型別又有無符號型別,當帶符號型別取值為負時會出現異常結果,這是因為帶符號數會自動地轉換成無符號數。
指定字面值的型別
字元和字串字面量
字首 | 含義 | 型別 |
---|---|---|
u | Unicode16字元 | char16_t |
U | Unicode32字元 | char32_t |
L | 寬字元 | wchar_t |
u8 | UTF-8(僅用於字串字面常量) | char |
整型字面值
字尾 | 最小匹配型別 |
---|---|
u or U | unsigned |
l or L | long |
ll or LL | long long |
浮點型字面值
字尾 | 型別 |
---|---|
f或F | float |
l或L | long double |
變數
物件是指一塊能儲存資料並具有某種型別的記憶體空間。
初始化與賦值
初始化:建立變數時賦予其一個初始值。
賦值:把物件的當前值擦除,而以一個新值來替代。
列表初始化
int units_sold{0};
C++11中當用於內建型別的變數時,如果我們使用列表初始化且初始值存在丟失資訊的風險,則編譯器報錯。
宣告與定義
宣告使得名字為程式所知,一個檔案如果想使用別處定義的名字則必須包含對那個名字的宣告。
定義負責建立與名字關聯的實體。定義還申請儲存空間。
如果想宣告一個變數而非定義它,就在變數名前新增關鍵字extern,而且不要顯式地初始化變數。
extern int i; //宣告i而非定義i
int j; //宣告並定義j
如果extern語句包含初始值就不再是宣告,而變成定義了。
extern int i = 345; //定義
在函式的內部無法初始化一個有extern關鍵字標記的變數。
::a 向全域性作用域發出請求獲取作用域操作符右側名字對應的變數。
引用
引用(reference)為物件起了一個另外一個名字,引用型別引用(refers to)另外一種型別。通過將宣告符寫成&d的形式來定義引用型別。
int ival = 1024;
int &refVal = ival; //refVal指向ival
int &refVal2; //報錯
引用必須要初始化!!!!!且無法令引用重新繫結到另外一個物件!!!!!!
引用即別名
引用並非物件,它只是為一個已經存在的物件所起的另外一個名字。
引用只能繫結在物件上,而不能與字面值或某個表示式的計算結果繫結在一起。
指標
引用不是物件,所有沒有實際地址,不能定義指向引用的指標!!!!!
空指標
得到空指標的最直接的辦法是用字面值nullptr來初始化指標(C++11標準)。nullptr是一種特殊型別的字面值,它可以被轉換成任意其他的指標型別。
新標準下C++最好使用nullptr,避免使用NULL。
建議:初始化所有指標
void*
void*指標是一個特殊的指標型別,可用於存放任意物件的地址。
void*的限制:
不能直接操作void*指標所指的物件。
指向指標的引用
int *p;
int *&r = p; //r是一個對指標p的引用
當遇到一個比較複雜的指標或引用的宣告語句時,從右向左閱讀有助於弄清楚它的真實含義。
const限定符
預設情況下,const物件被設定為僅在檔案內有效。當多個檔案中出現了同名的const變數時,其實等同於在不同檔案中分別定義了獨立的變數。
在不同檔案中共享同一const變數
對於const變數不管是宣告還是定義都新增extern關鍵字。
// file_1.cpp檔案
extern const int bufSize = fcn(); //定義並初始化了一個常量,該常量能被其他檔案訪問。
// file_1.h 檔案
extern const int bufSize; //與file_1.cpp中定義的bufSize是同一個。
如果想在多個檔案中共享const物件,必須在變數的定義之前新增extern關鍵字。
引用的型別必須與其所引用物件的型別一致,但是有兩個例外:
在初始化常量引用時,允許用任意表達式作為初始值,只要該表示式的結果能轉換成引用的型別即可。
常量引用僅對引用可參與的操作做出了限定,對於引用的物件本身是不是一個常量未作限定。
所謂指向常量的指標或引用,不過是指標或引用“自以為是”,它們覺得自己指向了常量,所以自覺地不去改變所指物件的值。
頂層const
頂層const可以表示任意的物件是常量,底層const則與指標和引用等複合型別的基本型別部分有關。
int i = 0;
int *const p1 = &i; //頂層const
const int ci = 42; //頂層const
const int *p2 = &ci; //底層const
const int *const p3 = p2; //底層const 頂層const
const int &r = ci; //底層const
當執行物件的拷貝操作時,頂層const不受什麼影響。
底層const的影響不能忽視,當執行物件的拷貝操作時,拷入和拷出的物件必須具有相同的底層const資格,或者兩個物件的資料型別必須能夠轉換。一般來說非常量可以轉換為常量,但常量不能轉換為非常量。
constexpr 和常量表達式
常量表達式是指不會改變並且在編譯過程就能得到計算結果的表示式。字面值屬於常量表達式,用常量表達式初始化的const物件也是常量表達式。
一個物件(或表示式)是不是常量表達式由它的資料型別和初始值共同決定。
constexpr 變數
C++11新標準規定,允許將變數宣告為constexpr型別以便由編譯器來驗證變數的值是否是一個常量表達式。宣告為constexpr的變數一定是一個常量,而且必須用常量表達式初始化。
constexpr int mf = 20;
constexpr int limit = mf + 1;
普通函式無法作為constexpr變數的初始值。新標準允許定義一種constexpr函式,可以用constexpr函式去初始化constexpr變數。
一個constexpr指標的初始值必須是nullptr或者0,或者是儲存於某個固定地址的物件。
類型別名
- typedef
typedef double wages; //wages是double的同義詞
typedef wages base, *p; //base是double的同義詞, p是double* 的同義詞。
- 別名宣告:
using SI = Sales_item; // SI是Sales_item的同義詞。
auto型別說明符
C++11新標準引入auto型別說明符,用它就能讓編譯器替我們去分析表示式所屬的型別。auto讓編譯器通過初始值來推算變數的型別,auto定義的變數必須有初始值。
- 編譯器以引用物件型別作為auto的型別
int i = 0, &r = i;
auto a = i; //a 是一個整數
- auto一般會忽略頂層const,同時底層const則會保留下來:
const int ci = i, &cr = ci;
auto b = ci; //b是一個整數(ci的頂層const特性被忽略)
auto c = cr; //c是一個整數
auto d = &i; //d是一個整型指標
auto e = &ci; // e是一個指向整數常量的指標
- 如果希望推斷出的auto型別是一個頂層const,需要明確指出:
const auto f = ci; // ci的推演型別是int, 但f是cosnt int 型別。
- 將引用的型別預設為auto:
auto &g = ci; //g是一個整型常量的引用,繫結到ci
auto &h = 42; //錯誤,不能為非常量引用繫結字面值
const auto &j = 42; //正確
設定一個型別為auto的引用時,初始值中的頂層常量屬性仍然保留。
decltype型別指示符
C++11引入了新的型別說明符decltype,它的作用是選擇並返回運算元的資料型別。編譯器分析表示式並得到它的型別,卻不實際計算表示式的值。
如果decltype使用的表示式是一個變數,則decltype返回該變數的型別(包含頂層const和引用在內).如果decltype使用的的表示式不是一個變數,則返回表示式結果所對應的型別。
如果表示式的內容是解引用操作,則decltype將得到引用型別!!!
!!!如果decltype的表示式是加上了括號的變數,結果將是引用。
!!!!decltype((variable))的結果永遠是引用,而decltype(variable)結果只有當variable本身是一個引用時才是引用!!!!
自定義資料結構
C++11新標準規定,可以為資料成員提供一個類內初始值。建立物件時,類內初始值將用於初始化資料成員。沒有初始值的成員將被預設初始化。