【C++】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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值