C++ const 和 constexpr 的区别?

constexpr 是 C++11 引入的,一方面是为了引入更多的编译时计算能力,另一方面也是解决 C++98 的 const 的双重语义问题。

在 C 里面,const 很明确只有 「只读」 一个语义,不会混淆。C++ 在此基础上增加了 「常量」 语义,也由 const 关键字来承担,引出来一些奇怪的问题。C++11「常量」 语义拆出来,交给新引入的 constexpr 关键字。

演示一下 const 关键字的双重语义可能带来的的问题:


template<int N> class C{};

constexpr int FivePlus(int x) { return 5 + x; }

void f(const int x) {
    C<x> c1; // Error: x is not compile-time evaluable.
    C<FivePlus(6)> c2; // OK
}

void g() {
    const int x = 5;
    C<x> c1; // OK!!! 此处用x的「常量」语义
    *(int *)(&x) = 6; // Still OK! 只处用x的「只读」语义,去除const后便可写了; (int*)是强制类型转换,有些编译器可能会报错
    // 如果上一句报错,就可以写成下面这一句:
    // *const_cast<int*>(&x) = 6;
    C<x> c2; // Still OK! c2是C<5>类型(不是C<6>!)
    C<FivePlus(x)> c3; // Still OK! c3是C<10>类型(不是C<11>!)

    printf("%d\n", x); // 此处绝大多数(所有?)C++编译器会输出5!!
                       // (然而,如果用一个C编译器来编译类似代码,一定输出6)
    const int* p = &x;
    printf("%d\n", *p); // 此处,大多数C++编译器输出6
}

可以看到,f 和 g 都有一个 const int x,但它们的行为却不同。原因在于:f 的 const int x 只是「一个只读的变量」;而 g 的 const int x 既是「一个只读的变量」,又是「一个值为5的常量」,变得飘忽不定。

在 C++11 以后,建议凡是 「常量」 语义的场景都使用 constexpr,只对 「只读」 语义使用 const

可能有人就会糊涂了,只读变量 难道不就是 常量吗?然则非也。
同样一个内存地址,用常量指针关联时,通过这一路径就无法修改;换用非常量指针 关联时,在这条路径上就是可以修改的。
换句话说,用 const 限定变量时,只是剥夺了通过该变量修改相应内存中内容的可能性,但是有可能其他程序或其他指向该内存地址的变量会改变这块内存中的内容,也就是说这块内存地址空间的内容并不会保证一直不变。所以,从现在开始,就把const理解成只读的限定符,把constexpr理解成常量的限定符。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值