0%

static,const,consexpr的总结对比

2020年5月4日 下午5:33
注:本文主要参考《C++ Primer》

总结:

  1. 我认为要区分这三个定义变量、函数、甚至是类中的使用方法,关键还是要站在需求的角度,千万别背,背会了也不会用。C++的设计者当初也是为了满足用户的需求在后期加上的这些功能,并且通过关键字的方式开放给程序员。

讲解static const的文章

c - Const vs Static Const - Stack Overflow
c - What is the difference between static const and const? - Stack Overflow

  • Addendum: Note that the behavior is different in C++. In C++, a const variable has internal linkage by default, so static const is redundant and extern const is necessary to get a constant with external linkage.

六个关键性的思考角度、概念:

  1. 名字作用域,对象声明周期 -> P184
  2. 编译,运行 -> P58
  3. 声明,定义 -> P41
  4. 有一个问题,为什么C++要设计六个概念?或者扩大点说,语言为什么要设计这些概念?
    1. 名字作用域,对象声明周期:域、周期都是表示的是范围的意思,在语言中加入范围的感念,可以有效的区分我们不再需要的定义、值,就像是标签一样,我们就可以将抛弃掉,有效的节省内存的使用
    2. 编译,运行 :关键是这里的编译,这其中就需要涉及到类型这个概念,动态类型语言不需要编译,静态类型需要需要编译(因为编译才定义成了静态类型语言),语言有了类型可以很好的帮助人类进行抽象,也可以进行进行类型的检查,将问题提前锁定在编译器更加安全
    3. 声明,定义:是C++为了运行程序拆分成多个逻辑部分来编写,所以支持了分离式编译,该机制允许将程序分割为若干的文件,每个文件可被单独编译。因此,C++将声明定义分开,这样就可以做到文件间共享代码的方法
      1. 声明:使得名字为程序所知,一个文件如果想使用别处定义的名字则必须包含对那个名字的声明
      2. 定义:负责创建于名字关联的实体

Static:全局变量 函数中 类中

  1. 全局变量:生命周期知道程序结束,作用域仅限于当前源文件
  2. 函数:P184局部对象->P43名字作用域,对象生命周期
    1. 自动对象->P40 默认初始化
    2. 局部静态对象
  3. 类:P269 类的静态成员
    1. 声明静态成员
    2. 使用类的静态成员
    3. 定义静态成员
    4. 静态成员的类内初始化
    5. 静态成员能用于某些场景,而普通成员不行

Constexpr:

  1. P58 constexpr常量表达式
    1. 常量表达式
    2. constexpr变量
    3. 字面值类型
    4. 指针和constexpr
  2. 函数中:P214
    1. constexpr函数
    2. 把内联函数和constexpr函数放在头文件内
  3. 类中:P267 字面值常量类
    1. constexpr构造函数

Const :

  1. static和const关键字的作用_JavaScript_许政的博客-CSDN博客
    1. 欲阻止一个变量被改变,可以使用const关键字。在定义该const变量时,通常需要对它进行初始化,因为以后就没有机会再去改变它了
    2. 对指针来说
      1. 可以指定指针本身为const,也可以指定指针所指的数据为const,或二者同时指定为const
    3. 在一个函数声明中
      1. const可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值
    4. 对于类的成员函数
      1. 若指定其为const类型,则表明其是一个常函数,不能修改类的 成员变量
    5. 对于类的成员函数
      1. 有时候必须指定其返回值为const类型,以使得其返回值不为“左值”
        1
        2
        3
        const classA operator*(const classA& a1,const classA& a2); //operator*的返回结果必须是一个const对象
        classA a, b, c;//如果不是,这样的变态代码也不会编译出错
        (a * b) = c; // 对a*b的结果赋值,显然不符合编程者的初衷,也没有任何意义
  2. 与constexpr的区别:
    1. constexpr的语义是:值在编译期就确定,并且在运行期不会改变。
    2. const指的是运行期:
      1. const变量的值可以在运行期再确定,编译器可以不确定,const保证的是运行期的不能改变变量的值,否则会报错
    3. 总结,constexpr和const最大的区别:值最晚什么时候确定,给的下限;并没有规定上限。
      1. const: |——————编译期———————|—————运行期———————|
      2. constexpr: |——————编译期———————|
      3. 上面表示的是值必须在指定区间中确定,否则出错
    4. eg:P58
      1. 使用const的常量表达式
        1
        2
        3
        4
        5
        6
        7
        8
        9
        // 常量表达式
        const int max_files = 20;//max_files是常量表达式
        const int limit = max_files + 1;//limit是常量表达式
        // 非常量表达式
        int staff_size = 27;//staff不是常量表达式
        const int sz = get_size();//sz不是常量表达式
        /*
        1.尽管staff_size的初始值是一个字面常量,但是由于他的数据类型只是普通的int而非const int,所以他不属于常量表达式
        2.尽管sz本身是一个常量,但是他的具体值知道运行时才能或得到,所以也不是常量表达式
      2. 使用constexpr的常量表达式
        1
        2
        3
        4
        // constexpr类型以便编译器来验证变量的值是否是一个常量表达式
        constexpr int mf = 20;//20是常量表达式
        constexpr int limit = mf + 1;//mf + 1是常量表达式
        constexpr int sz = size();//只有size是一个constexpr函数时,才是一条正确的声明语句