正文之前
看了一天《C++ Primer 第五版》,好爽啊!不過收獲不是很大,而且還有不少的地方不太懂,但是還是把我的收獲分享出來!希望大家喜歡吼~~
正文
1、 頂層const
- 眾所周知,指針本身就是一個對象,不依附于別的對象而存在著,也就意味著指針定義的時候不需要初始化。所以對于指針這個東西來說。其本身與其所指向的對象是不是常量本身就是獨立的事情。那么我們用頂層const來表示指針本身就是一個常量,也就是常指針,用底層const來表示指針所指向的對象是常量,那么我們可以知道:
const int i=21;
const int *const p= &i
代表著p是一個指向常量的常指針,也就是說其本身就兼具了頂層const和底層const的特性。
- 注意注意!!必須在* 跟p之間加一個const,才是表示的常指針,否則兩個const就是重復定義:
修改之后就是完整的指向常量的常指針:
- 如果只有一個const:
const int i=21;
const int *p= &i
那么其實這個意思是,p是一個指針,指向一個const常量,沒錯,const只用來表示&i中的i是一個常量,而不管你p這個指針的效果。
- 所以兩個const 定義的話是分別給p加持了頂層和底層的const特性,如果只有一個const ,那么上面的代碼是底層const ,也就是說是指向常量,本身不是常指針。下面是常指針,頂層const的特性:
const int i=21;
int *const p= &i;
- 另外,注意!!拷貝操作,必須是拷貝方與被拷貝方有著相同的底層const特性(頂層特性不考慮),否則是會報錯的,如下:
const int i=21;
const int *p1=&i;
const int *p2=p1; //正確,因為p2已經在const那兒申明了我是指向一個常量的,所以因為p1具備底層const 可以被p2拷貝
int *p3=p1; //所以這毫無疑問是錯誤的,因為你p3啥const特性都不具備,咋去拷貝一個具有底層const特性的指針?
別問我為啥,C++11就這么規定的!要從計算機組成說我還沒學那么深!另外其實每一個直接定義常量的都是天生具備頂層const特性,比如const int i=21;
2、 constexpr和常量表達式
- 常量表達式兩大特性:
- 本身值不會改變,const type
- 能夠在編譯過程中得到計算結果,而不需要等別的輸入
就好比下面:
const int max=1;
const int min=size();
第一行的max就是常量表達式,而第二行的min就不是,因為size()必須在運行之后才知道結果。
constexpr變量,這個跟const很像。constexpr是新標準中允許變量聲明為constexpr以便由編譯器驗證變量是不是常量表達式而產生的!具體的作用后面說,我也還沒摸清楚
至于constexpr的另一個特性,那就是如果用它定義一個指針,那么它只針對指針,而對指針指向的對象毫不關心(官方術語是:constexpr把其定義的對象置為頂層const)。下面是區別所在:
const int *p=&i; //定義了一個指向整形常量的非常量指針;
constexpr int *p=&i; //定義了一個指向整數的常量指針!!
- 如果要定義指向常量的常量指針,那么就需要下面這一句:
constexpr const int *p=&i
3、 類型別名
類型別名有兩種方法:
- 傳統的方式是:
typedef
typedef double wages;
此時的話,見wages如見double。你可以用wages做任何double能做的事情:
wages file=12.1;
typedef wages *base;
上面兩句中,第一句定義了一個雙精度的變量file并且初始化了。第二句則是給wages *(相當于是double * )
再次定義了一個別名,那就是base ,所以以后base就代表了“double類型的指針變量”這一個固定標簽。但是有一個巨坑,那就是要跟宏定義區分開來!!!這個是超級重要的!下面見例子:
typedef double *base;
const base cs=&hi;
const double *cs1=&hi;
如果一不小心,我們會以為cs是一個指向常量hi的指針,指針對象本身是一個非常量,跟第三行cs1是一樣的。但是事實是:cs是一個指向double的常量指針,base據定了它是一個指向double的指針,然后const再限定了cs是一個常量,這是針對指針本身的,其效果等同于
double *const cs=&hi; // === const base cs=&hi;
- 另外一種別名方式是:
using
using base =double;
上述兩種方式效果等同。
4、 auto類型說明符
- auto的作用是讓編譯器代替我們去分析表達式所述的類型。但是請注意,auto一次只能分析一種類型,無法分析多種,也就是說,如下:
auto i=0,*p=&i;
auto sz=0,pi=3.14;
第一句是對的,可以分析出來,auto在第一句中等效int,而第二句中,sz是int類型,pi是浮點數,很顯然是無法同時自動判定兩種類型的, 所以報錯了!!
- auto的一些特性
1)auto在引用中忽略”引用“這一類型,而是直接返回引用綁定的對象類型
int i=0,&r=i;
auto a=r; //(這里的auto會返回一個int 類型 而不是int &這個引用的類型)
2)auto會忽略頂層的const ,但是會保留底層const,比如說:
const int ci=i;
auto b=ci;
auto c=&ci
*c=i;
3)看得出來,b是自動忽略了ci的頂層const特性,而不會忽略底層特性,所以第四行會報錯,如下圖:
4)如果希望auto類型被推斷出一個頂層const特性,那么如下即可:
const auto f=ci;
5)設置一個引用的時候,會保留頂層常量的屬性,因此初始值必須是相同的類型的,下面一對一錯:
auto &m=ci,*p=&ci; //都是對整形常量的引用
auto &n=i,*p2=&ci; // 這就錯了。n是對非常量i的引用,是int ,而p2對ci的引用時const int 所以不行
5、 decltype 類型提示符
這個類型提示符類似于一個類型的提取,可以返回括號內的表達式的返回類型。比如說:
- decltype(F()) 那么它整體就代表著F()函數的返回類型,如果是int 那么可以這么用:
decltype(F()) a=10; //a是整形變量;
- 另外
decltype()
對于引用和const
都會全盤返回,比如說:
const int i=10,&m=i;
decltype(m) x=i
第二句就相當于是 const int & x=i;
也就是說const
與&
這兩個操作都被返回
下面是我總結的集中
decltype()
返回引用類型的情況
- 指針解引用 ,如 :
int i=10;
int *p=i;
decltype(*p) x=i
第三句等效于 int &x=i
;返回的是引用int &
而不是int
本身就是一個引用,上面說過了;
如果
decltype((X))
,也就是說括號內還有一個括號把變量包含在內,那么就是返回的這個變量加上& ,比如如果X是int變量,那么前面返回 int &賦值語句會返回引用
decltype(a=b)
返回的就是a的類型的引用, 比如如果a是int
變量,那么前面返回int &
正文之后
今天之所以現在就出來了。是因為晚上基本沒怎么看書,去寫簡書去了。所以晚上我就沒怎么看書,現在十點半已經快寫完了,每天寫寫簡書,撈撈粉絲,賺點人氣,爽歪歪~ ~ 待會再看會《金粉世家》和《計算機學科導論》,這樣的日子才是我大頭張應該過的嗎~ ~