隨著程序的越來(lái)越復(fù)雜,程序中用到的類型也越來(lái)越復(fù)雜,體現(xiàn)在兩個(gè)方面:
- 類型名稱難于拼寫,名字既難記由容易寫錯(cuò),還無(wú)法確定其真實(shí)目的是什么
- 有時(shí)候根本不知道所需要的類型是什么,我們必須從上下文尋求幫助
這時(shí)候我們主要有三種解決方案:
- 類型別名
類型別名是一個(gè)名字,是某種類型的一個(gè)同義詞。
傳統(tǒng)方法定義別名用的是typedef:
typedef double wages; //wages是double的同義詞
wages hourly, weekly; //等同于double hourly, weekly;
C++11標(biāo)準(zhǔn)規(guī)定了一種新的辦法,即使用別名聲明,using:
using wages = double; //wages是double的同義詞
wages hourly, weekly; //等同于double hourly, weekly;
這里需要注意的是,假如某個(gè)類型別名指代的是復(fù)合類型或者常量,那么把它用到聲明語(yǔ)句里就會(huì)產(chǎn)生意想不到的后果:
typedef char *pstring;
const pstring cstr = 0; //cstr指向char的常量指針
const pstring *ps; //ps是一個(gè)指針,它的對(duì)象是指向char的常量指針
這里必須要明白,pstring實(shí)際上是指向char的指針,所以const pstring就是指向char的常量指針,而非指向常量字符的指針,不能簡(jiǎn)單的將類型別名替換成他本來(lái)的樣子:
const char *cstr = 0; //這是對(duì)const pstring cstr的錯(cuò)誤理解
2.auto類型說(shuō)明符
在我們編程的時(shí)候,常常需要把表達(dá)式的值賦值給變量,這要求在聲明變量的時(shí)候知道表達(dá)式的類型,然而這一點(diǎn)是很不容易的,所以C++11引入了auto說(shuō)明符來(lái)幫助我們推斷表達(dá)式所屬的類型,由auto的特性我們知道,auto定義的變量必須有初始值。
這里我們要注意的是,auto可以在同一條語(yǔ)句中聲明多個(gè)變量,但是一條語(yǔ)句中只能有一個(gè)基本數(shù)據(jù)類型,所以該語(yǔ)句中所有的初始基本數(shù)據(jù)類型都必須一樣:
auto i = 0, *p = &i; //正確,i是整型,p是整型指針
auto sz = 0, pi = 3.14 //錯(cuò)誤,sz是整型, pi是浮點(diǎn)型
使用auto我們還必須要注意以下幾點(diǎn):
- 首先,和我們之前所知道的一樣,使用引用其實(shí)就是使用引用的對(duì)象,特別的是,當(dāng)引用作為初始值的時(shí)候,參與初始化的實(shí)際上是引用的對(duì)象的值。所以,編譯器此時(shí)以引用對(duì)象的類型作為auto的類型:
int i = 0, &r = i;
auto a = r; //a是int型(r是i的別名,而i是int型)
- 其次,auto一般會(huì)忽略頂層const,同時(shí)底層const會(huì)被保留下來(lái):
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型常量的指針
- 如果希望推斷出來(lái)的是一個(gè)頂層const,需要明確的指出:
const auto f = ci; //ci的推演類型是int,而f是const int
- 還可以將引用的類型設(shè)置為auto,此時(shí)原來(lái)的初始化規(guī)則仍然適用:
auto &g = ci; //g是一個(gè)整型常量引用,綁定到ci
auto &h = 42; //錯(cuò)誤,非常量引用不可綁定字面值
const auto &j = 42; //正確,常量引用綁定字面值
設(shè)置一個(gè)auto的引用的時(shí)候,初始值中的頂層常量屬性仍然保留
- 要在一條語(yǔ)句中定義多個(gè)變量,切記,符號(hào)&和*只從屬于某個(gè)聲明符,而非基本數(shù)據(jù)類型的一部分,因此初始值必須是同一種類型:
auto k = ci, &l = i; //k是int型, l是int型引用
auto &m = ci, *p = &ci; //m是int型常量引用,p是指向int型常量的指針
auto &n = i, *p2 = &ci //錯(cuò)誤,n是int型引用,而p2必須是指向int型常量的指針,這里確實(shí)指向int型的普通指針
3.decltype類型指示符
有時(shí)候會(huì)碰到這樣的情況,我們想用某個(gè)表達(dá)式的類型定義某個(gè)變量,但是不想用該表達(dá)式的值初始化這個(gè)變量。C++11給我們提供了decltype說(shuō)明符,它的作用是返回操作數(shù)的數(shù)據(jù)類型。
decltype處理底層const和引用的方式與auto不同。如果decltype使用的表達(dá)式是一個(gè)變量,那么decltype返回該變量的類型(包括頂層const和引用在內(nèi)):
const int ci = 0, &cj = ci;
decltype(ci) x = 0; //x的類型是const int
decltype(cj) y = x; //y的類型是const int &
decltype(cj) z; //錯(cuò)誤,z的類型是const int &,必須初始化
下面讓我們看一組有趣的情況:
int i = 42, *p = &i, &r = i;
decltype(r + 0) b;
decltype(*p) c
在上述的代碼中,decltype(r + 0)返回的類型是int型,這是因?yàn)?,r作為表達(dá)式的一部分,r + 0實(shí)際上參與運(yùn)算的是i + 0,返回的是一個(gè)具體的值,而非引用,是int型,但是decltype(r)返回的類型是int &,這點(diǎn)需要明白。
最后一點(diǎn)需要懂得的是,如果decltype使用的是一個(gè)不加括號(hào)的變量,那么得到的結(jié)果是這個(gè)變量的類型,一旦加上括號(hào),得到的是引用類型:
decltype((i)) d; //錯(cuò)誤,d是一個(gè)int &,必須初始化
decltype(i) e; //正確,e是一個(gè)為初始化的int型變量