const限定符

  1. 任何試圖爲const變量賦值的操作都將引發錯誤
  2. const對象一旦創建就不可再改變,所以const對象必須初始化
  3. 編譯器將在編譯過程中,把用到const變量的地方用相應的值替換
  4. 默認情況下,const對象被設定爲僅在文件內有效;當多個文件中出現了同名的const變量時,等同於在不同文件中分別定義了獨立的變量
  5. 若想在多個文件之間共享const對象,必須在變量的定義之前添加extern關鍵字
  6. 不允許非常量引用指向一個常量對象;因爲若假設該初始化方法合法,那麼則可以通過該非常量引用來改變引用對象的值,顯然引用對象作爲const變量的是不能被改變的;見test_1
  7. 當常量引用有類型轉換情況存在時,編譯器會產生一個臨時變量進行綁定(即需要一個空間來暫存表達式的求值結果時創建的一個未命名的對象);當非常量引用有類型轉換情況存在時,C++定義其爲非法;見test_2
  8. 對const的引用和指向const常量的指針沒有規定其所指向的對象必須是一個常量;只是說不能通過該引用或指針來改變對象的值,而沒有規定那個對象的值不能通過其他途徑改變;見test_3
  9. 常量指針必須在初始化的時候指向某個地址,即必須初始化;在初始化之後該常量指針不可指向別處,但指向的對象可以發生改變(如果指向的對象是變量則可以通過常量指針修改對象的值,如果指向的對象是常量則不可);見test_4
  10. 指針是不是常量和指針所指的對象是不是常量,是兩個相互獨立的問題;頂層const表示指針本身是個常量,底層const表示指針所指的對象是一個常量
  11. 常量表達式是指值不會改變並且在編譯過程就能得到計算結果的表達式;例如:字面值和用常量表達式初始化的const對象
  12. 在複雜系統中,很難分辨一個初始值到底是不是常量表達式,爲了防止由編碼人員自行推斷出現的錯誤;C++11規定,允許將變量聲明爲constexpr類型以由編譯器來驗證變量是否是一個表達式;聲明爲constexpr的變量一定是一個常量,而且必須用常量表達式初始化;見test_5
  13. 常量表達式的值需要在編譯時就得到計算,因此對聲明constexpr變量的類型有一定的限制;這些類型比較簡單和容易得到,故也稱作“字面值類型”;包括:算術類型、引用和指針,類、IO庫、string類型則不屬於字面值類型,因此也就不能用constexpr進行修飾
  14. 儘管指針和引用都能定義成constexpr,但它們的初始值受到嚴格限制。一個constexpr指針的初始值必須是nullptr或者0,或者是存儲於某個固定地址中的對象;例如像函數體內定義的變量一般不是存放在固定地址中,因此constexpr指針一般不出現在函數體內部;見test_5
  15. constexpr int *pointer 和 const int *pointer 意義是不同的;前面表示的是常量指針,後面表示指針對象是常量;constexpr int *pointer 和 int * const pointer 意義相同
/**
 * @Author: phd
 * @Date: 2019/12/13
 * @Site: github.com/phdsky
 * @Description: NULL
 */

#include <iostream>

using namespace std;

void test_1() {
  const int const_int = 1024;
  // int &reference_int = const_int; // error: binding value of type 'const int' to reference to type 'int' drops 'const' qualifier
  const int &const_reference_int = const_int;
}

void test_2() {
  double value_double = 3.14;
  const int &const_reference_int = value_double;
  cout << "double val addr: " << &value_double << endl;
  cout << "const int val addr: " << &const_reference_int << endl;
  cout << "Note compiler produced a new const temp for const_reference_int to binding !" << endl;

  // int &reference_int = value_double; // error: non-const lvalue reference to type 'int' cannot bind to a value of unrelated type 'double'
}

void test_3() {
  // reference
  int value_int = 42;
  int &reference_int = value_int;
  const int &const_reference_int = value_int;

  reference_int = 0;
  // const_reference_int = 0; // error: cannot assign to variable 'const_reference_int' with const-qualified type 'const int &'

  // pointer
  const double const_double = 3.14;
  // double *double_pointer = &const_double; // error: cannot initialize a variable of type 'double *' with an rvalue of type 'const double *'

  const double *const_double_pointer = &const_double;
  // const_double_pointer = 6.28; // error: assigning to 'const double *' from incompatible type 'double'
}

void test_4() {
  int value_int = 233;
  const int const_value_int = 2333;

  int * const int_const_pointer = &value_int;

  // int * const int_cosnt_pointer = &const_value_int; // error: cannot initialize a variable of type 'int *const' with an rvalue of type 'const int *'
  const int * const const_int_const_pointer = &const_value_int;

  // wanna to change pointer's point
  // const_int_const_pointer = &value_int; // error: cannot assign to variable 'const_int_const_pointer' with const-qualified type 'const int *const'

  // wanna to change value
  *int_const_pointer = 666;
  // *const_int_const_pointer = 6666; // error: read-only variable is not assignable
}

const int return_const_value() {
  return 2333;
}

constexpr int return_consexpr_value() {
  return 233333;
}

constexpr int constexpr_int_outer = 666;

void test_5() {
  const int const_int = 233;
  const int const_int_another = const_int + 1; // Is a const expression
  const int const_int_other = return_const_value(); // Is not a const expression, because function value can be obtained only after running

  constexpr int constexpr_int = 2333;
  constexpr int constexpr_int_another = constexpr_int + 1; // Is a const expression
  constexpr int constexpr_int_other = return_consexpr_value(); // Is a const expression

  cout << const_int_other << " " << constexpr_int_other << endl;

  // constexpr int *constexpr_int_pointer = &constexpr_int; // error: cannot initialize a variable of type 'int *const' with an rvalue of type 'const int *'
  // int * const int_const_pointer = &constexpr_int; // error: same as above

  const int * const_int_pointer = &constexpr_int;
  int const * int_const_pointer = &constexpr_int; // fuck, they are the same

  // constexpr const int *const_int_constexpr_pointer = &constexpr_int; // error: constexpr variable 'const_int_constexpr_pointer' must be initialized by a constant expression
  constexpr const int *const_int_constexpr_pointer_another = &constexpr_int_outer;  // must defined outer the function body
}

int main(int argc, char *argv[]) {
  test_1();
  test_2();
  test_3();
  test_4();
  test_5();

  return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章