處理類型

隨著程序的越來越復雜,程序中用到的類型也越來越復雜,體現在兩個方面:

  • 類型名稱難于拼寫,名字既難記由容易寫錯,還無法確定其真實目的是什么
  • 有時候根本不知道所需要的類型是什么,我們必須從上下文尋求幫助

這時候我們主要有三種解決方案:

  1. 類型別名
    類型別名是一個名字,是某種類型的一個同義詞。
    傳統方法定義別名用的是typedef
typedef double wages;      //wages是double的同義詞
wages hourly, weekly;       //等同于double hourly, weekly;

C++11標準規定了一種新的辦法,即使用別名聲明,using:

using wages = double;    //wages是double的同義詞
wages hourly, weekly;     //等同于double hourly, weekly;

這里需要注意的是,假如某個類型別名指代的是復合類型或者常量,那么把它用到聲明語句里就會產生意想不到的后果:

typedef char *pstring;
const pstring cstr = 0;    //cstr指向char的常量指針
const pstring *ps;          //ps是一個指針,它的對象是指向char的常量指針

這里必須要明白,pstring實際上是指向char的指針,所以const pstring就是指向char的常量指針,而非指向常量字符的指針,不能簡單的將類型別名替換成他本來的樣子

const char *cstr = 0;     //這是對const pstring cstr的錯誤理解

2.auto類型說明符
在我們編程的時候,常常需要把表達式的值賦值給變量,這要求在聲明變量的時候知道表達式的類型,然而這一點是很不容易的,所以C++11引入了auto說明符來幫助我們推斷表達式所屬的類型,由auto的特性我們知道,auto定義的變量必須有初始值。
這里我們要注意的是,auto可以在同一條語句中聲明多個變量,但是一條語句中只能有一個基本數據類型,所以該語句中所有的初始基本數據類型都必須一樣

auto i = 0, *p = &i;        //正確,i是整型,p是整型指針
auto sz = 0, pi = 3.14   //錯誤,sz是整型, pi是浮點型

使用auto我們還必須要注意以下幾點:

  • 首先,和我們之前所知道的一樣,使用引用其實就是使用引用的對象,特別的是,當引用作為初始值的時候,參與初始化的實際上是引用的對象的值。所以,編譯器此時以引用對象的類型作為auto的類型:
int i = 0, &r = i;
auto a = r;               //a是int型(r是i的別名,而i是int型)
  • 其次,auto一般會忽略頂層const,同時底層const會被保留下來:
const int ci = i, &cr = ci;
auto b = ci;                      //b是int型(ci的頂層const被忽略)
auto c = cr;                      //c是int型(cr是ci的別名,ci的頂層const被忽略)
auto d = &i;                      //d是指向int型的指針
auto e = &ci;                     //e是指向int型常量的指針
  • 如果希望推斷出來的是一個頂層const,需要明確的指出:
const auto f = ci;      //ci的推演類型是int,而f是const int
  • 還可以將引用的類型設置為auto,此時原來的初始化規則仍然適用:
auto &g = ci;             //g是一個整型常量引用,綁定到ci
auto &h = 42;            //錯誤,非常量引用不可綁定字面值
const auto &j = 42;   //正確,常量引用綁定字面值

設置一個auto的引用的時候,初始值中的頂層常量屬性仍然保留

  • 要在一條語句中定義多個變量,切記,符號&和*只從屬于某個聲明符,而非基本數據類型的一部分,因此初始值必須是同一種類型:
auto k = ci, &l = i;         //k是int型, l是int型引用
auto &m = ci, *p = &ci;  //m是int型常量引用,p是指向int型常量的指針
auto &n = i, *p2 = &ci    //錯誤,n是int型引用,而p2必須是指向int型常量的指針,這里確實指向int型的普通指針

3.decltype類型指示符
有時候會碰到這樣的情況,我們想用某個表達式的類型定義某個變量,但是不想用該表達式的值初始化這個變量。C++11給我們提供了decltype說明符,它的作用是返回操作數的數據類型。
decltype處理底層const和引用的方式與auto不同。如果decltype使用的表達式是一個變量,那么decltype返回該變量的類型(包括頂層const和引用在內)

const int ci = 0, &cj = ci;
decltype(ci) x = 0;            //x的類型是const int
decltype(cj) y = x;             //y的類型是const int &
decltype(cj) z;                  //錯誤,z的類型是const int &,必須初始化

下面讓我們看一組有趣的情況:

int i = 42, *p = &i, &r = i;
decltype(r + 0) b;
decltype(*p) c

在上述的代碼中,decltype(r + 0)返回的類型是int型,這是因為,r作為表達式的一部分,r + 0實際上參與運算的是i + 0,返回的是一個具體的值,而非引用,是int型,但是decltype(r)返回的類型是int &,這點需要明白。

最后一點需要懂得的是,如果decltype使用的是一個不加括號的變量,那么得到的結果是這個變量的類型,一旦加上括號,得到的是引用類型

decltype((i)) d;    //錯誤,d是一個int &,必須初始化
decltype(i)  e;     //正確,e是一個為初始化的int型變量
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容