【C++Primer筆記】第二章 變數和基本型別
技術標籤:C++Primer筆記c++
第二章 變數和基本型別
資料型別決定著變數所佔記憶體空間大小、該空間所能儲存的值的範圍,以及變數能參與的運算。
文章目錄
算術型別
-
基本內建型別使用法則:
- 數值確定不為負,用
unsigned
; - 使用
int
進行整數運算。如果大於int
(216=65536, 28=32768),使用long long
型(字面值末尾加LL); - 在算術表示式中不要用
char
或bool
(char
是否有符號視機器而定,而bool
- 執行浮點數運算用
double
(單精度6位,雙精度10位)。
- 數值確定不為負,用
-
賦給無符號型別一個超出它表示範圍的初始值時,結果是初始值模表示數值總數後的值(如
unsigned char
型別的-1相當於模256後的255).而賦給有符號型別一個超範圍的值時,結果是未定義的。一個算術表示式中既有無符號數又有int
時,後者會自動轉換為無符號數。切勿混用帶符號型別和無符號型別! -
20 //20十進位制 024 //20八進位制 0x14 //20十六進位制
-
轉義序列:反斜線、問號、雙引號、單引號前面都要加\。
泛化的轉義序列:\x後面跟一個十六進位制數字,或者\後面跟一個不超過三位的八進位制數字。
定義和宣告
-
使用列表初始化時,如果初始值存在丟失資訊的風險,編譯器會報錯。
double val = 3.141592653; int a = {val}; //報錯 int b = val; //不報錯
-
**定義於任何函式體之外的變數被初始化為0(包括
main
函式),而定義在函式體內部的內建型別變數不被初始化。**不被初始化的變數,值是未定義的(Codeblocks
裡是隨機數)。建議初始化每一個內建型別變數。 -
如果要在多個檔案中使用同一個變數,就必須把宣告和定義分離:在一個檔案中定義變數(不一定要加
extern
),而在其他檔案中對其進行宣告。extern int i; //不能初始化,否則則為定義
-
**當你第一次使用變數時,再去定義它!**在內層作用域中,可以重新定義外層作用域已有的名字。這樣,前者會覆蓋後者。再次訪問後者需要使用
::
操作符。如果函式可能用到一個全域性變數,則不應再定義一個同名的區域性變數。
引用和指標
-
複合型別:引用和指標。**引用只是為一個已有物件起的別名,本身並不是物件(而指標本身是一個物件)。引用無法解綁,必須初始化(和指標不同)。引用、指標型別必須和物件型別嚴格匹配。**定義方式如下:
int *p1, p2, &r3; //p1是指標,p2是int型物件,p3是引用
-
只有有效指標才能解引用。
void*
型指標可以存放任意型別物件的地址,但不能解引用,只能用作函式輸入輸出、和其他指標比較,或者賦值給另一個void*
指標。 -
空指標:
int *p1 = nullptr; int *p2 = 0;
-
等定義物件後再定義指向它的指標。若實在不知道指標指向何處,就初始化為
nullptr
。 -
賦值改變的是永遠是等號左側的物件!
-
不存在指向引用的指標(因為引用不是物件),但是存在對指標的引用:
int val = 32; int *p = &val; int *&r = p; //r是一個對指標p的引用
Const
-
凡是定義後不能更改的變數必須初始化。如
const
型變數、引用變數。 -
const
物件預設情況下只在檔案內有效。如果要多個檔案共用,定義和宣告時都要加extern
。 -
允許一個對
const
的引用(常量引用)繫結非常量物件、字面值、表示式。而普通引用無法繫結到常量物件或常量引用身上。雖然不能修改常量引用的值,但仍能通過其他途徑修改被引用的物件。int i = 42; const int &r = i; i = 0; r = 1; //錯誤!
-
指向常量的指標與常量引用類似(底層
const
):只是不能通過解引用修改指向的物件而已,通過其他途徑修改還是可以的。但是這種指標可以不用初始化,也可以改變它的指向。 -
常量指標本身是一個常量,所以必須初始化,且不能修改其值(地址)。還是可以通過從右往左原則記憶(最右邊的代表其屬性)。
int i; const int *i1; //指向常量的指標 int *const i2 = &i; //常量指標
-
對頂層
const
(普通、常量指標)的拷貝沒有限制。而對於底層const
(常量引用和指向常量的指標),只能常量之間拷貝,或者非常量轉換為常量。
Constexpr
-
只有包含
const
修飾符、初始值為字面值型別(或為用常量表達式初始化的const
物件)的表示式才是常量表達式(注:字面值型別包括整型(包括布林型和字元型)、浮點型、引用和指標)。const int max = 100; //max是常量表達式 const int limit = max + 1; //limit是常量表達式 int is = 27; //is不是常量表達式 const int s = getSize(); //s不是常量表達式
-
宣告為
constexpr
的變數(頂層const
)一定是一個常量。如果認定一個變數是常量表達式,就把它宣告為constexpr
。 -
constexpr
指標只能初始化為nullptr
或常量的地址。不過,由於定義於所有函式之外的變數的地址固定不變,它們是可以用來初始化constexpr
指標的。注意寫法:constexpr int *p = 0; //和指向常量的指標是完全不同的!
處理型別
typedef
-
類型別名的宣告方法:
typedef double wages; //傳統方法 typedef wages base, *p; //p是double*型別 // using wages = double; //C++11的新方法
注意:
typedef char *p; const p cspr = 0; //cspr是一個常量指標,而不是指向常量的指標
auto
-
auto
型別說明符能讓編譯器自主判斷型別。顯然,auto
定義的變數必須初始化。一條宣告語句中所有變數的初始基本資料型別必須相同。double val1, val2; auto val = val1 +val2; //由右側的表示式推出val是double型 auto sz = 0, pi = 3.14; //錯誤!
-
auto
預設會忽略掉引用和頂層const
特性:int i = 0, &r = i; auto a = r; //a是整型變數,而非對整型的引用 const int ci = i, &cr = ci; auto b = ci; //b是整型變數(頂層const) auto c = &cr; //c是指向整型常量的指標(底層const)
-
如果想要推出頂層
const
型,要在auto
前面加上const
。 -
設定一個型別為
auto
的引用時,初始值中的頂層屬性仍然保留,且原來的初始化規則仍然適用。auto &g = ci; //g是一個整型常量引用 auto &h = 42; //錯誤!不能為非常量引用繫結字面值 const auto &j = 42; //正確!
decltype
-
decltype()
返回運算元的資料型別(當你想知道這個表示式的資料型別,而又不想用這個表示式的值作為初始值的時候,用decltype
而不用auto
)。 -
decltype
返回的型別包括引用和頂層const
在內(引用從來都只作為其引用物件的同義詞(代名詞)出現,只有在decltype
是個例外)。 -
一些使用法則:
int i = 32, *p = &i, &r = i; decltype(r+0) b; //正確!使用加法後變為整型,而非整型引用 decltype(*p) c; //錯誤!指標解引用後返回引用型別,要初始化 decltype((i)) d; //錯誤!兩個括號得到引用型別
自定義資料結構
-
建議定義分開寫,不要合在一起:
struct Data{...}; Data d1, d2;
-
標頭檔案通常包含類、
const
變數、constexpr
變數等。 -
標頭檔案保護符:為了防止重複定義某一標頭檔案。
#ifndef SALES_DATA_H //如果還沒被定義過 #define SALES_DATA_H //定義 #include <string> //string標頭檔案裡也寫了標頭檔案保護符,就不會被重複定義 struct SalesData { std::string bookName; double revenue = 0.0; }; #endif