zoukankan      html  css  js  c++  java
  • 3、const与constexpr

    初遇到constexpr真的是有点懵比,看了很多博客也没看懂,不知道是我太笨,还是别人写的太深奥?总之经过一番折腾算是入门了。一下是我个人总结,有不对的地方望指出。

    一、学习const与constexpr必须要先知道一下几个概念:

    1、constexpr是constant expression的缩写。顾名思义“常量 表达式”

    2、何为常量表达式(constant expression):是指由编译器求值的表达式。

          在这里在解释一下编译器求值概念:编译系统由预处理器、编译器、汇编器、连接器四部分组成

          一个源文件到一个可执行文件要经过这四部分,所谓的编译器求值指的就是第二部分编译器部分,

    二、  C++中的const与constexpr都是与“常量”有关的两个概念。

    1、C++中的const兼容了C语言中的const。

    (1)C语言中的const:

            ① 编译器可以把声明带 const 限定类型的对象放到只读内存中。

            ② const 语义仅应用到左值表达式

            ③  指代 const 限定类型对象的左值表达式,和指代拥有至少一个 const 限定类型成员(包含为聚合体或联合体所递归含有的成员)的结构体或联合体的左值表达式,不是可修改左值。具体而言,它们不可赋值:

    const int n = 1; // const 类型对象
    n = 2; // 错误: n 的类型为 const 限定
     
    int x = 2; // 无限定类型对下
    const int* p = &x;
    *p = 3; // 错误:左值 *p 的类型为 const 限定
     
    struct {int a; const int b; } s1 = {.b=1}, s2 = {.b=2};
    s1 = s2; // 错误: s1 的类型无限定,但它有 const 成员

          const 限定的结构体或联合体类型的成员,取得它所属类型的限定版本(在用 . 运算符或 -> 运算符访问时)。

    struct s { int i; const int ci; } s;
    // s.i 的类型为 int , s.ci 的类型为 const int
    const struct s cs;
    // cs.i 和 cs.ci 的类型都是 const int

    若以 const 类型限定符声明数组类型(通过使用 typedef ),则数组类型无 const 限定,但其元素类型有。若以 const 类型限定符声明函数类型(通过使用 typedef ),则行为未定义。

    typedef int A[2][3];
    const A a = {{4, 5, 6}, {7, 8, 9}}; // const int 的数组的数组
    int* pi = a[0]; // 错误: a[0] 拥有 const int* 类型

    指向非 const 类型的指针能隐式转换成指向同一或兼容类型的 const 限定版本的指针。能用转型表达式进行逆向转换。

    int* p = 0;
    const int* cp = p; // OK :添加限定符( int 到 const int )
    p = cp; // 错误:舍弃限定符( const int 到 int )
    p = (int*)cp; // OK :转型

    注意指向指向 T 指针的指针不可转换为指向指向 const T 指针的指针;对于要兼容的二个类型,其限定必须等同。

    char *p = 0;
    const char **cpp = &p; // 错误: char* 与 const char* 不是兼容类型
    char * const *pcp = &p; // OK :添加限定符( char * 到 char *const )

    2、constexpre的用法:

    • constexpr - 指定变量或函数的值可在常量表达式中出现
    • 解释

      constexpr 说明符声明可以在编译时求得函数或变量的值。然后这些变量和函数(若给定了合适的函数实参)即可用于仅允许编译时常量表达式之处。用于对象或非静态成员函数 (C++14 前)声明的 constexpr 说明符蕴含 const。用于函数声明的 constexpr说明符或 static 成员变量 (C++17 起)蕴含 inline。若函数或函数模板的任何声明拥有 constexpr 说明符,则每个声明必须都含有该说明符。

    • constexpr 变量必须满足下列要求: 

    • 其类型必须是字面类型 (LiteralType) 
    • 它必须被立即初始化
    • 其初始化的全表达式,包括所有隐式转换、构造函数调用等,都必须是常量表达式

    constexpr 函数必须满足下列要求:

    (C++20 前)
    • 函数体必须被弃置或预置,或只含有下列内容:
    (C++14 前)
    • 函数体必须含:
    • goto 语句
    • 拥有除 case 和 default 之外的标号的语句
    (C++20 前)
    • 非字面类型的变量定义
    • 静态或线程存储期变量的定义

    (=default; 或 =delete; 的函数体不含任何上述内容。)

    (C++14 起)
  • 相关阅读:
    【GoLand】分享项目到Github平台
    【Git】实用教程
    【Go】Mac系统下安装GoLand 及 环境配置
    CF 901C Bipartite Segments
    CF 811E Vladik and Entertaining Flags
    Luogu P6300 悔改
    Luogu P3943 星空
    CSP2020 | T4
    NOIP2017 | D2T3
    Luogu P6852 Mex
  • 原文地址:https://www.cnblogs.com/tito/p/12357310.html
Copyright © 2011-2022 走看看