C 型別處理 typedef decltype

2022-02-02 22:38:24 字數 3541 閱讀 4791

型別別名是某種型別的同義詞

有兩種方法用於定義型別別名,傳統方法是使用typedef

typedef double wages;  //wages是double的同義詞

typedef wages base, *p //base是double的同義詞,p是double*的同義詞

新標準規定了一種新的方法,使用別名宣告來定義型別別名:

using si = sales_item; //si是sales_item的同義詞
把等號左側的名字規定成等號右側型別的別名

型別別名和型別的名字等價,只要是型別的名字能出現的地方,就能使用型別別名

si item; //等價於sales_item item;
typedef char *pstring;

const pstring cstr = 0; //cstr是指向char的常量指標

const psrting *ps; //ps是指向「指向char的常量指標」的指標

我們可能錯誤的嘗試替換成typedef前的樣子:

const char *cstr = 0;   //這是const pstring cstr的錯誤理解
const pstring cstr表示cstr是指向char的常量指標,而不是腦內「翻譯」得到的const char *cstr(表示指向常量char的指標)

我們常常需要把表示式的值賦給變數,這就要求在宣告變數時清楚的知道表示式的型別,然而這一點並非那麼容易,有時根本做不到,c++11為解決這個問題引入了auto型別說明符

auto item = val1 + val2
使用auto也能在一條語句中宣告多個變數,但要注意一條宣告語句只能有乙個基本資料型別

auto i = 0, *p = &i;   //正確:i是整數,p是整形指標

auto sz = 0, pi = 3.14 //錯誤,型別不一致

編譯器推斷的auto型別有時候和初始值型別不完全一樣,而是會適當地改編結果型別使其更復合初始化規則

int i = 0, &r = i;

auto a = r; //a是乙個整數(r是i的別名,而i是乙個整數)

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是乙個指向整數常量的指標(對常量物件取位址是底層const)

吐過希望推斷出的auto型別是乙個頂層const,我們就要明確指出:

const auto f = ci;
我們還可以將引用型別設為auto,此時原來的初始化規則仍然適用

auto &g = ci;         //g是乙個整形常量的引用,繫結到ci

auto &h = 42; //錯誤:不能為非常量引用繫結字面值

const auto &j = 42; //正確:可以為常量引用繫結字面值

設定乙個型別為auto的引用時,初始值中的頂層常量屬性仍按保留,如果我們給初始值繫結乙個引用,此時的常量就不是頂層常量了

有一種情況:我們希望從表示式型別推斷出要定義的變數型別,但是不想用該表示式的值初始化變數(如果要初始化就用auto了)

為了滿足這一需求,c++11引入了第二種型別說明符decltype,它的作用是選擇並返回運算元的資料型別

在此過程中,編譯器分析表示式並且得到他的型別,卻不是及計算表示式的值

decltype(f()) sum = x; //sum的型別就是函式f的返回型別
編譯器不實際呼叫函式f,而是使當呼叫發生時,f的返回值作為sum的型別

decltype處理頂層const和引用的方式與auto有些不同

如果decltype使用的表示式是乙個變數,則decltype返回改變量的型別(包括頂層const和引用在內)

const int ci = 0, &cj = ci;

decltype(cj) x = 0; //x的型別是const int

decltype(cj) y = x; //y的型別是const int&,y繫結到變數x

decltype(cj) z; //錯誤:z是乙個引用,必須被初始化

int x = 0,y = 1;

typedef decltype(x+y) xytype;

xytype xpy = x + y;

//decltype:推斷x+y的型別,這個地方是int;

//typedef:把decltype(x+y)起個別名為xytype,即xytype表示int;

//可以像int那樣使用xytype

如果decltype使用的表示式不是乙個變數,則decltype返回表示式結果對應的型別

有些表示式將向decltype返回乙個引用型別,一般這種情況,意味著該表示式的結果物件能作為一條賦值語句的左值:

int i = 42, *p = &i, &r = i;

decltype(r+0) b; //正確:加法的結果是int,因此b是乙個int(未初始化)

decltype(*p) c; //錯誤:c是int&,必須初始化

因為r是乙個引用,因此decltype(r)的結果是引用型別,如果想讓結果型別是r所指的型別,可以把r作為表示式的一部分,比如上面的r+0,顯然這個表示式的結果不是引用而是具體值

另一方面,如果表示式的內容是解引用操作,的decltype將得到引用的型別

decltype(*p)的結果型別就是int&而不是int

如果變數名不加括號,得到的結果就是該變數的型別

如果加上一層或者多層括號,編譯器就會把它當作乙個表示式

(變數是一種可以作為賦值語句左值的特殊表示式,所以這樣decltype會得到引用型別

decltype((i)) d; //錯誤:d是int&,必須初始化

decltype(i) e; //正確,e是乙個int(未初始化)

切記decltype((variable))的結果永遠是引用

而decltype(variable)只有當variable本身就是乙個引用時,才是引用

C 型別處理

引用本身不是乙個物件,所以不能定義指向引用的指標,但指標是物件,所以存在指標的引用。可以通過從右往左理解為什麼p是乙個指標的引用,p的左邊是引用符號,因此p是乙個引用,其餘部分表示p引用的是乙個int指標。int main 頂層const表示指標本身是乙個常量,底層const表示指向的物件是乙個常量...

C 動態資料型別處理

通過反射獲取物件後動態對屬性賦值,由於欄位為不同的資料型別,所以要根據欄位的型別進行賦值。方法1.網上常見的根據datatype寫很多ifelse的 方法2 利用convert.changetype方法,根據當前欄位的資料型別動態轉換賦值 object obj1 convert.changetype...

c (13)處理型別 型別別名

型別別名 是乙個名字,它是某種型別的同義詞。使用型別別名的好處 它讓複雜的型別名字變的簡單明瞭,易於理解和使用,還有助於程式設計師清楚的知道使用該型別的真實目的。有兩種方法可以定義型別別名 1.傳統的方法是使用關鍵字typedef typedef double d d是double的同義詞 type...