1. 程式人生 > >const限定符、constexpr和常量表達式------c++ primer

const限定符、constexpr和常量表達式------c++ primer

rim 同文件 其他 而不是 將在 ron 必須 常量 限制

  編譯器將在編譯過程中把用到const變量的地方都替換成對應的值,為了執行這種替換,編譯器必須知道變量的初始值。如果程序包含多個文件,則那個用了const對象的文件都必須能訪問到它的初始值才行。要做到這一點,就必須在每一個用到變量的文件中都有對它的定義。為了支持這一用法,同時避免對同一變量的重復定義,默認情況下,const對象被設定為僅在文件內有效。當多個文件中出現了同名的const變量時,其實等同於在不同文件中分別定義了獨立的變量。

  某些時候有這樣一種const變量,它的初始值不是一個常量表達式,但又確實有必要在文件間共享。在這種情況下,我們不希望編譯器為每個文件分別生成獨立的變量。相反,我們想讓這類const對象像其他(非常量)對象一樣工作,也就是說,只在一個文件種定義cons,而在其他多個文件中聲明並使用它。

  解決的辦法是,對於const變量不管是聲明還是定義都添加extern關鍵字,這樣只需定義一次就可以了:

	// file_1.cc定義並初始化了一個常量,該常量能被其他文件訪問
	extern const int bufsize = fcn();

	// file_1.h頭文件
	extern const int bufsize;//與file_1.cc中定義的bufsize是同一個

  因為bufsize是一個常量,必須用extern加以限定使其被其他文件使用。

  file_1.h頭文件中的聲明也由extern做了限定其作用是指明bufsize並非本文件所獨有,它的定義將在別處出現。

  如果想在多個文件之間共享const對象,必須在變量的定義之前添加extern關鍵字。

  const double *cptr;指向常量的指針。不能用於改變其所指對象的值,可指向非常量的對象,所謂指向常量的指針僅僅要求不能通過該指針改變對象的值,而沒有規定那個對象的值不能通過其他途徑改變,

  double const *cptr;常量指針,即不變的是指針本身的值而不是指針指向的那個值。

  用頂層const 表示指針本身是個常量,用底層const 表示指針所指的對象是一個常量。

const int *const p3=p2;//靠右的const是頂層const,靠左的是底層const

  

constexpr和常量表達式

  常量表達式(const expression)是指值不會改變並且在編譯過程中就能得到計算結果的表達式

。一個對象(或表達式)是不是常量表達式由它的數據類型和初始值共同決定,例如:

const int max=20;//max是常量表達式
const int li=max+1;//li是常量表達式
int sta=27;//sta不是常量表達式
const int sz=get();//sz不是常量表達式

  盡管sz本身是一個常量,但它的具體值知道運行時才能獲取到,所以也不是常量表達式。

constexpr變量

  constexpr類型將由編譯器來驗證變量的值是否是一個常量表達式。聲明為constexpr的變量一定是一個常量,而且必須用常量表達式初始化:

constexpr int mf=20;//20是常量表達式
constexpr int li=mf+1;//mf+1是常量表達式
constexpr int sz=size();//只有當size是一個constexpr函數時才是一條正確的聲明語句

  如果認定變量是常量表達式,那就把它聲明成constexpr類型,只有字面值類型才能定義成constexpr。

到目前為止接觸過的數據類型中,算術類型、引用和指針都屬於字面值類型,IO庫,string類型則不屬於字面值類型,也就不能被定義成constexpr

  盡管指針和引用都能定義成constexpr,但它們的初始值卻受到嚴格限制,一個constexpr指針的初始值必須是nullptr或者0,或者是存儲於某個固定地址中的對象。

  constexpr指針不能指向函數體內定義的變量(因為一般來說並非存放在固定地址中)。

  定義於所有函數體之外的對象其地址固定不變,能用來初始化constecpr指針。

指針和constexpr

  在constexpr聲明中如果定義了一個指針,限定符僅對指針有效,於指針所指的對象無關;

  constexpr指針既可以指向常量也可以指向一個非常量。

const限定符、constexpr和常量表達式------c++ primer