2.4:const限定符

独自空忆成欢 提交于 2020-02-06 05:26:41

这是个好东西,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在*右边,指针为常量

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

顶层const:任意对象本身是常量

底层const:指针所指的对象是一个常量,与复合类型有关

执行拷贝操作时:顶层const不受影响,底层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指针

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!