1. 程式人生 > >2.4:const限定符

2.4:const限定符

容易 常量 變量 常量表達式 指針 編譯器 是不是 都得 訪問

這是個好東西,Effective C++裏都已說過:能用的地方盡量用,大師都這樣說了,我們這些渣渣為何不遵循?

const就是常量,這就有個重要的東西了:常量必須初始化

  const int a = 0;

  const int b = get_size();  //已知有get_size()函數

  const int c;       //錯誤!!!

---------------------------------------------------------------------------------------------------------------

  int m = 42;

  const int n = m;

---------------------------------------------------------------------------------------------------------------

對const對象的任何修改都會導致錯誤。

  const a = 0;

  a = 1;      //錯誤!!

==============================分割線==============================

默認狀態下,const對象僅在文件內有效

當定義一個const對象時,編譯器會在編譯過程(#define是在預處理階段)中將用到該變量的地方都替換成對應的值。

為了執行這個替換,編譯器必須知道變量的初始值,如果有多個文件,每個文件都得定義這個變量。當多個文件中出現同名的const變量時,其實等同於在不同的文件中分別定義了獨立的變量。如果想在一個文件中定義了,在其他文件中使用,可以用關鍵字extern。

  extern const int a = 0; //文件1.cpp中定義並初始化了一個常量,能被其他文件訪問

  extern const int a;  //在2.cpp中,與1.cpp是一個常量

==============================分割線==============================

初始化和對const的引用,const引用可以綁定到一個並非const對象上

  int i = 0;

  const int &r1 = i;    //允許將const int&綁定到一個普通int對象上

  const int &r2 = 42;  //正確

  const int &r3 = r1 * 2; //正確

  int &r4 = r1 * 2;    //錯誤,r4是普通引用

具體原因見C++primer P55

==============================分割線==============================

指針和const:

  主要是兩種:

  1、指向常量的指針:意思是指針指向的那個對象時常量,不可以改變,但是指針本身可以改變指向的對象

  const int num = 0;

  int *ptr1 = #     //錯誤,ptr1是普通指針

  const int *ptr2 = #  //正確,ptr2是一個指針常量的指針

  const int num1 = 1;

  ptr2 = &num1;       //正確

  2、常量指針:必須初始化,是指針本身就是常量,也就是指針不能改變它指向的位置,但是指針所指的對象可以改變值

  int num = 0;

  int *const ptr = #  //ptr將一直指向num的地址,不能改變

  num = 1;         //正確,可以改變num

  int num1 = 1;

  ptr = &num1;       //錯誤,不能改變ptr指向的地址

  其實很簡單,分辨方法,如果const在*左邊那麽,物為常量;const在*右邊,指針為常量

==============================分割線==============================

constexpr和常量表達式

  1、常量表達式:指不會改變並且在編譯過程就能得到計算結果的表達式,因此,字面值屬於常量表達式,用於常量表達式初始化的const對象也是常量表達式。

  const int num = 0;        //num是常量表達式

  const int num1 = num + 1;    //num1是常量表達式

  int num3 = 0;          //num3不是常量表達式

  const int temp = get_size();    //temp不是常量表達式,因為結果需要在運行時才能獲取

  2、constexpr變量

  在一個復雜系統中,很難分辨一個初始值到底是不是常量表達式。C++11新標準中,允許將變量聲明為constexpr類型以便由編譯器來驗證變量的值是否是一個常量表達式。聲明為constexpr的變量一定是一個常量,而且必須用常量表達式初始化。

  constexpr int num0 = 1;      //1是常量表達式

  constexpr int num1 = num0 + 1;   //num0 + 1是常量表達式

  constexpr int sz = size();       //只有當size是一個constexpr函數時才能聲明成功

  3、字面值類型

  一個類型簡單、值顯而易見、容易得到,在編譯時就能得到,就為字面值類型

  算術類型,引用,指針都屬於字面值類型。自定義類,IO庫,string類型都不屬於字面值類型,也就不能定義為constexpr。

  4.指針和constexpr

  如果constexpr聲明中定義了一個指針,那麽constexpr只對指針有效,與指針所指的對象無關

  const int *ptr1 = nullptr;     //ptr1是一個指向整數型常量的指針

  constexpr int *ptr2 = nullptr;   //ptr2是一個指向整數的常量指針

  兩者區別見const指針

2.4:const限定符