C++的constexpr与const

一、constexpr的介绍

constexpr是C++11开始提出的关键字,功能是使指定的常量表达式获得在程序编译阶段计算出结果的能力,而不必等到程序运行阶段。以定义数组为例,数组的长度就必须是一个常量表达式。

注:所谓常量表达式,指的就是由多个常量组成的表达式。

如下代码,我们可以看到

    // 1)
    int url[10]; //正确

    // 2)
    int url[6 + 4]; //正确

    // 3)
    int length = 6;
    int url[length]; //错误,length是变量

二、constexpr使用

constexpr所修饰的变量一定是编译期可求值的

 constexpr  int foo( int i)
 {
	 return i + 5;
 }

 int main()
 {
	 constexpr  int  a = foo(1); // ok
	 constexpr  int  b = foo(cin.get()); // !error
	 constexpr  int  c = a * 2 + 1; // ok 

 }

以下编译失败,对于funcTest,胆小的编译器并没有足够的胆量去做编译期优化,哪怕函数体就一句return 字面值

 const int funcTest() {
	 return 10;
 }

 int main()
 {
	 int arr[funcTest()];
     return 0;
 }
//error : 函数调用在常量表达式中必须具有常量值

修改后,编译通过,编译期大胆地将funcTest()做了优化,在编译期就确定了func计算出的值10而无需等到运行时再去计算。

 constexpr int funcTest() {
	 return 10;
 }

 int main()
 {
	 int arr[funcTest()];
 }

三、与const的比较

 我们发现,const 关键字在实际使用中经常会表现出两种不同的语义。举个例子:

    #include <iostream>
    #include <array>
    using namespace std;

    void dis_1(const int x){
        //错误,x是只读的变量
        array <int,x> myarr{1,2,3,4,5};
        cout << myarr[1] << endl;
    }

    void dis_2(){
        const int x = 5;
        array <int,x> myarr{1,2,3,4,5};
        cout << myarr[1] << endl;
    }

    int main()
    {
       dis_1(5);
       dis_2();
       return 0;
    }

可以看到,dis_1() 和 dis_2() 函数中都包含一个 const int x,但 dis_1() 函数中的 x 无法完成初始化 array 容器的任务,而 dis_2() 函数中的 x 却可以。

这是因为,dis_1() 函数中的“const int x”只是想强调 x 是一个只读的变量,其本质仍为变量,无法用来初始化 array 容器;而 dis_2() 函数中的“const int x”,表明 x 是一个只读变量的同时,x 还是一个值为 5 的常量,所以可以用来初始化 array 容器。

有读者可能会问,“只读”不就意味着其不能被修改吗?答案是否定的,“只读”和“不允许被修改”之间并没有必然的联系,举个例子:

    #include <iostream>
    using namespace std;

    int main()
    {
        int a = 10;
        const int & con_b = a;
        cout << con_b << endl;
        a = 20;
        cout << con_b << endl;
        return 0;
    }

 

可以看到,程序中用 const 修饰了 con_b 变量,表示该变量“只读”,即无法通过变量自身去修改自己的值。但这并不意味着 con_b 的值不能借助其它变量间接改变,通过改变 a 的值就可以使 con_b 的值发生变化。 

为了解决 const 关键字的双重语义问题,保留了 const 表示“只读”的语义,而将“常量”的语义划分给了新添加的 constexpr 关键字。因此 C++11 标准中,建议将 const 和 constexpr 的功能区分开,即凡是表达“只读”语义的场景都使用 const,表达“常量”语义的场景都使用 constexpr。

在大部分实际场景中,const 和 constexpr 是可以混用的,例如:

const int a = 5 + 4;

constexpr int a = 5 + 4;

 四、总结

  1. constexpr是一种很强的约束,更好地保证程序的正确语义不被破坏。
  2. 编译器可以在编译期对constexpr的代码进行非常大的优化,比如将用到的constexpr表达式都直接替换成最终结果等。
  3. constexpr相比宏来说,没有额外的开销,但更安全可靠。

参考:

C++11/14 constexpr 用法 - 简书

C++总结:C++中的const和constexpr_jfkidear的博客-CSDN博客_constexpr

C++11 constexpr和const的区别详解

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值