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.修饰类(未完待续)

  • 相关阅读:
    管道通信
    进程间的八种通信方式----共享内存是最快的 IPC 方式
    归并排序时间复杂度
    vector中的push_back函数的意思是什么
    如何实现android和服务器长连接
    android中实现service动态更新UI界面
    android中如何实现UI的实时更新---需要考虑电量和流量
    Map集合排序
    (二十一)自定义Tabbar
    (二十)首页内容详细【详细页】+ 评论 + 回复
  • 原文地址:https://www.cnblogs.com/cauchy007/p/4966067.html
Copyright © 2011-2022 走看看