zoukankan      html  css  js  c++  java
  • C++11新标准:constexpr关键字

    一、constexpr意义

      将变量声明为constexpr类型以便由编译器来验证变量是否是一个常量表达式(不会改变,在编译过程中就能得到计算结果的表达式)。是一种比const更强的约束,这样可以得到更好的效率和安全性。

    二、constexpr用法

      1.修饰函数

    /*1.如果size在编译时能确定,那么返回值就可以是constexpr,编译通过*/
    constexpr int getSizeA(int size)
    {
        return 4*size;
    }
    /*2.编译通过,有告警:在constexpr中定义变量*/
    constexpr int getSizeB(int size)
    {
        int index = 0;
        return 4;
    }
    /*3.编译通过,有告警:在constexpr中定义变量(这个有点迷糊)*/
    constexpr int getSizeC(int size)
    {
        constexpr int index = 0;
        return 4;
    }
    /*4.编译通过,有告警:使用了if语句(使用switch也会告警)*/
    constexpr int getSizeD(int size)
    {
        if(0)
        {}
        return 4;
    }
    /*5.定义变量并且没有初始化,编译不过*/
    constexpr int getSizeE(int size)
    {
        int index;
        return 4;
    }
    /*6.rand()为运行期函数,不能在编译期确定,编译不过*/
    constexpr int getSizeF(int size)
    {
        return 4*rand();
    }
    /*7.使用了for,编译不过*/
    constexpr int getSizeG(int size)
    {
        for(;0;)
        {}
        return 4*rand();
    }

      总结:constexpr修饰的函数,不能依赖任何运行期的信息,不要定义任何变量常量,并且必须尽量简单,要不就会编译不过或告警(坑)。

       2.修饰类型

        int tempA;
        cin>>tempA;
        
        const int ctempA = 4;
        const int ctempB = tempA;
        /*1.可以再编译器确定,编译通过*/
        constexpr int conexprA = 4;
        constexpr int conexprB = conexprA + 1;
        constexpr int conexprC = getSizeA(conexprA);
        constexpr int conexprD = ctempA;
        /*2.不能在编译期决定,编译不过*/
        constexpr int conexprE = tempA;
        constexpr int conexprF = ctempB; 

      总结:constexpr修饰的常量必须在编译期确定值,上面的例子也体现出了和const之间的差别。const既可以在编译期确定如ctempA,也可以在运行期确定如ctempB,使用范围更广。还有一点constexpr只能修饰字面值类型如算数类型、引用类型、指针以及后面介绍的字面值常量类。

      3.修饰指针

    int g_tempA = 4;
    const int g_conTempA = 4;
    constexpr int g_conexprTempA = 4;
    
    int main(void)
    {
        int tempA = 4;
        const int conTempA = 4;
        constexpr int conexprTempA = 4;
        
        /*1.正常运行,编译通过*/
        const int *conptrA = &tempA;
        const int *conptrB = &conTempA;
        const int *conptrC = &conexprTempA;
        /*2.局部变量的地址要运行时才能确认,故不能在编译期决定,编译不过*/
        constexpr int *conexprPtrA = &tempA;
        constexpr int *conexprPtrB = &conTempA
        constexpr int *conexprPtrC = &conexprTempA;
        /*3.第一个通过,后面两个不过,因为constexpr int *所限定的是指针是常量,故不能将常量的地址赋给顶层const*/
        constexpr int *conexprPtrD = &g_tempA;
        constexpr int *conexprPtrE = &g_conTempA
        constexpr int *conexprPtrF = &g_conexprTempA;
        /*4.局部变量的地址要运行时才能确认,故不能在编译期决定,编译不过*/
        constexpr const int *conexprConPtrA = &tempA;
        constexpr const int *conexprConPtrB = &conTempA;
        constexpr const int *conexprConPtrC = &conexprTempA;
        /*5.正常运行,编译通过*/
        constexpr const int *conexprConPtrD = &g_tempA;
        constexpr const int *conexprConPtrE = &g_conTempA;
        constexpr const int *conexprConPtrF = &g_conexprTempA;
    
        return 0;
    }

      总结:constexpr指针不能用局部变量赋值,const指针可以;constexpr指针里是顶层const,即指针是常量,而不是所指向的类型是常量,如果要指向的类型也为常量,要用constexpr const来修饰。

    4.修饰引用

    int g_tempA = 4;
    const int g_conTempA = 4;
    constexpr int g_conexprTempA = 4;
    
    int main(void)
    {
        int tempA = 4;
        const int conTempA = 4;
        constexpr int conexprTempA = 4;
        /*1.正常运行,编译通过*/
        const int &conptrA = tempA;
        const int &conptrB = conTempA;
        const int &conptrC = conexprTempA;
        /*2.有两个问题:一是引用到局部变量,不能再编译器确定;二是conexprPtrB和conexprPtrC应该为constexpr const类型,编译不过*/
        constexpr int &conexprPtrA = tempA;
        constexpr int &conexprPtrB = conTempA 
        constexpr int &conexprPtrC = conexprTempA;
        /*3.第一个编译通过,后两个不通过,原因是因为conexprPtrE和conexprPtrF应该为constexpr const类型*/
        constexpr int &conexprPtrD = g_tempA;
        constexpr int &conexprPtrE = g_conTempA;
        constexpr int &conexprPtrF = g_conexprTempA;
        /*4.正常运行,编译通过*/
        constexpr const int &conexprConPtrD = g_tempA;
        constexpr const int &conexprConPtrE = g_conTempA;
        constexpr const int &conexprConPtrF = g_conexprTempA;
    
        return 0;
    }

      总结:简单的说constexpr所引用的对象必须在编译期就决定地址。还有一个奇葩的地方就是可以通过上例conexprPtrD来修改g_tempA的值,也就是说constexpr修饰的引用不是常量,如果要确保其实常量引用需要constexpr const来修饰。

    5.修饰类(未完待续)

  • 相关阅读:
    一起学习Avalonia(三)
    一起学习Avalonia(一)
    .NetCore(Avalonia) 项目dll混淆,deb安装包解压,重新打包
    .Net 桌面程序(winform,wpf,跨平台avalonia)打安装包部署到windows 入门
    .net 跨平台桌面程序 avalonia:从项目创建到打包部署linux-64系统deepin 或 ubuntu。
    【JAVA习题十八】求1+2!+3!+...+20!的和
    【JAVA习题十七】有一分数序列:2/1,3/2,5/3,8/5,13/8,21/13...求出这个数列的前20项之和。
    【JAVA习题十六】打印菱形
    【JAVA习题十五】两个乒乓球队进行比赛,各出三人。甲队为a,b,c三人,乙队为x,y,z三人。已抽签决定比赛名单。有人向队员打听比赛的名单。a说他不和x比,c说他不和x,z比,请编程序找出三队赛手的名单。
    【JAVA习题十四】猴子吃桃问题:猴子第一天摘下若干个桃子,当即吃了一半,还不瘾,又多吃了一个 第二天早上又将剩 下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下 的一半零一个。到第10天早上想再吃时,见只剩下一个桃子了。求第一天共摘了多少。
  • 原文地址:https://www.cnblogs.com/cauchy007/p/4966067.html
Copyright © 2011-2022 走看看