1. 變數和基本型別
變數和基本型別
浮點數用double
,整數一般int
,超過範圍用long long
,知道沒負數用unsigned
。
變數使用extern
進行宣告,宣告不是定義,使用該關鍵字後,不要進行顯式初始化操作,變數可以宣告多次,但是隻能定義一次。
引用:
int r2=10;
int &r1=r2;
r1
和r2
是同一個資料,只是名稱不同。
void*
指標可以存放任意物件的地址。
int* p, p1; // p是int*類型,而p1是int型別,這樣寫容易誤解
int *p2, p3; // 這是規範寫法
const
限定符僅僅在檔案的內部有效,且必須進行初始化,否則無意義,編譯時會找到變數名進行替換,類似於#define
const
變數,前面必須使用extern
進行說明
const
可以進行引用,但是對常量的引用不能修改它繫結的物件
const int ci=1024;
const int &r1=ci; // 正確
r1=ci; // 錯誤,r1是對常量的引用
int &r2=ci; // 錯誤,非常量不能引用常量
int i=10;
// 正確,但是不允許通過r2修改i的值,始終和i的值一致,r2不可以繫結其他變數
const int &r2=i;
const
可以用於指標:
double d=10;
const double *p=d; // 不能通過p修改d的值,但是可以改變p的指向
double *const p1=d; // p1始終指向d
const double *const p2=d; // p2始終指向d,而且不能用p2修改d的值
頂層const
表示指標本身是個常量;底層const
表示指標所指的物件是個常量,但本身的指向可以變。更一般的,頂層const
表示任意物件是常量。
int i=0;
int *const p1=&i; // 頂層const,p1只能指向i
const int ci=i; // 頂層const,ci的值不能變
const int *p2=i; // 底層const,p2的值可以變
const int *const p3=p2; // 右側是頂層const,左側是底層const
const int &r=ci; // 用於宣告引用的都是底層的const
頂層const
可以表示任意的物件是常量。進行拷貝時,物件對須有相同的底層const
資格!
常量表達式是值不會改變而且在編譯過程就能得到計算結果的表示式。字面值是常量表達式,用常量表達式初始化的const
物件也是。
const int max_files=20; // 是
const int limit=max_files+1; // 是
int staff_size=11; // 不是
const int sz=get_size(); // 不是
constexpr
型別的變數,用於由編譯器來驗證變數的值是否是常量表達式,宣告為該型別的變數一定是一個常量,且必須用常量表達式進行初始化。一般來說,如果變數是一個常量表達式,那麼就宣告為constexpr
型別。
constexpr int mf=20; // 20是常量表達式
constexpr int limit=mf+1; // mf+1是常量表達式
constexpr int sz=size(); // 只有size是constexpr函式時,才是正確的語句
字面值型別是編譯期間就知道的,像算數型別、引用和指標等;而IO庫,string
型別等則不是。用constexpr
宣告的指標初始化必須是0、nullptr
或者儲存於耨個固定地址中的物件。
類型別名:
// 兩種別名的模式
typedef double dle;
using flt=float;
auto
自動型別推導,編譯器自動進行型別的推斷。使用auto
時,一條語句中的基本型別只能有一個。
auto i=0, *p=&i; // 正確,都是int的推導
auto sz=1, pi=3.14; // 錯誤,出現了int和double
auto
對引用變數進行推導時,實際參與初始化的是引用物件的值。
int i=0,&r=i;
auto a=r; // 實際上是i參與初始化
auto
推導時,忽略頂層的const
,保留底層的const
。
int i=0;
const int ci=i,&cr=ci;
auto b=ci; // b是整數,忽略頂層的const
auto c=cr; // c是整數,忽略頂層的const
auto d=&i; // d是整型指標
auto e=&ci; // 指向整數常量的指標
如果需要頂層常量,需要自己標出:
const auto f=ci;
需要推導引用,也需要自己指出來:
auto &g=ci;
或者兩者都用:
const auto &tmp=ci;
decltype
型別指示符,選擇並返回運算元的型別。
decltype(f()) sum=x; // sum的型別就是f返回的型別
上述的例子中,編譯器不實際呼叫函式f
,而是使用當發生f
呼叫時返回的型別作為sum
的實際值。decltype
處理頂層的const
和引用時,如果使用的表示式是一個變數,則返回變數的型別(包括頂層的const和引用在內):
const int ci=0,&cj=ci;
decltype(ci) x=0; // x的型別是const int
decltype(cj) y=x; // y的的型別是const int & 繫結到x上
decltype(cj) z; // 錯誤,引用必須初始化
表示式的內容是解引用,則decltype
會得到該型別的引用。
int i=42,*p=&i,&r=i;
decltype(r+0) b; // 加法的結果是int,因此b是未初始化的int
decltype(*p)c; // 錯誤,c是int& 必須初始化
decltype((variable))
(雙層括號)的結果永遠是引用,decltype(variable)
(一層括號)只有當variable
本身是一個引用時才是引用。