C++11新特性之十七:constexpr

本文详细介绍了C++11中的constexpr关键字,包括其基本概念、如何定义constexpr变量及函数,以及constexpr在模板编程中的应用等。同时展示了constexpr在提高程序效率方面的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

constexpr是在 C++11 被引进的关键字,它的字面意思是 constant expression,常量表达式。它可以作用在变量和函数上。一个 constexpr 变量是一个编译时完全确定的常数。一个 constexpr 函数至少对于某一组实参可以在编译期间产生一个编译期常数。在C++11之后的标准中赋予了constexpr更多的特性,比如C++14 允许在 constexpr 函数中使用局部变量,从而支持了循环;在 C++17 的时候多了 if constexpr 这样的语法,使得模板编程的可读性更好......。本文仅讨论C++11中的constexpr 
我们可以通过将变量声明为 constexpr 来要求它在编译期被初始化:

void f(int x)
{
    int y1 = x;
    constexpr int y2 = x;   // Error
    constexpr int y3 = 77;  // OK
    
    int m = 1;
    const int n = 2;
    constexpr int y4 = m;   // Error
    constexpr int y5 = n;   // OK
}

用constexpr修饰的函数,返回值不一定是编译期常量,这是特性,不是bug。

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

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

int main()
{
    int i = 10;
    std::array<int, foo(5)> arr; // OK
    
    foo(i); // Call is Ok
    
    // But...
    std::array<int, foo(i)> arr1; // Error
}

constexpr修饰的函数,简单的来说,如果其传入的参数可以在编译时期计算出来,那么这个函数就会产生编译时期的值。但是,传入的参数如果不能在编译时期计算出来,那么constexpr修饰的函数就和普通函数一样了。不过,我们不必因此而写两个版本,所以如果函数体适用于constexpr函数的条件,可以尽量加上constexpr。而检测constexpr函数是否产生编译时期值的方法很简单,就是利用std::array需要编译期常值才能编译通过的小技巧。这样的话,即可检测你所写的函数是否真的产生编译期常值了。
用constexpr修饰的函数还可以当做模板参数。

template<int N> class C{};
constexpr int FivePlus(int x) {
  return 5 + x;
}

void f(const int x) {
  C<x> c1;   // Error
  C<FivePlus(6)> c2;  // OK
} 

比如你想特化一个模板,在传入的模板参数是std::numeric_limits<int>::max()时报错。那么在没有constexpr之前,就没救了,只能用INT_MAX宏......。当然现在Max已被constexpr修饰,是可以正常当模板参数传入的,原理和FivePlus函数一样。
当然引进constexpr最主要的原因是效率,因为编译器知道这是一个常量,所以可以优化代码,比如整个function全部优化掉,从而提高运行速度。

#include <iostream>
#include <chrono>

using namespace std::chrono;

constexpr int Calculate1 (int x, int y)
{
    return x * x + y * y;
}
int Calculate2 (int x, int y)
{
    return x * x + y * y;
}

int main()
{
    auto start1 = high_resolution_clock::now();
    for(int i = 0;i < 1000000; i++)
    {
        // 是常量表达式
         Calculate1 (11, 12);
    }
    auto end1 =  high_resolution_clock::now();
    std::cout <<"cost time: " << duration_cast<microseconds>(end1 - start1).count()<<" us" << std::endl;

    auto start2 = high_resolution_clock::now();
    for(int i = 0;i < 1000000; i++)
    {
        // 不是常量表达式, 返回值不能用constexpr修饰
        Calculate2 (11, 12);
    }
    auto end2 =  high_resolution_clock::now();
    std::cout <<"cost time: " << duration_cast<microseconds>(end2 - start2).count() << " us" << std::endl;
    return 0;
}

可以看到循环100万次,函数Caculate1耗时更少,如果用变量接收函数返回值,对比更明显。

constexpr int ret = Calculate1 (11, 12);
int ret = Calculate2 (11, 12);

原文链接:C++11新特性之十七:constexpr-优快云博客 

【为什么要使用PHPWAMP集成环境,而不是其他集成环境呢?】 1、因为PHPWAMP解压即可使用,你甚至不需要安装VC运行库也可直接运行,而其他的集成环境都需要你额外去安装vc运行库,下载费时间,安装也费时间。 2、PHPWAMP默认集成的各个组件都是最新版本的,而且是完整版,所以更加适合在服务器上运行(其他集成环境通常用来测试的,集成的组件阉割过,体积小很多)当然PHPWAMP也很适合在本地测试,如果包括32位和64位、线程安全与非线程安全的PHP版本,共计700多个PHP版本随便你切换。 3、PHPWAMP可以同时运行各个不同版本的PHP网站,十分适合对比测试。多版本同时运行也适合在服务器上运行那些对php版本要求比较严格的PHP程序,可在服务器上同时运行不同php版本的网站程序。 4、关键这货还能一键去除域名后面的端口号,实现与Apache、Nginx、IIS等WEB服务器共存时,去掉域名后面的端口号。 5、兼容性很强,兼容XP系统、windows7、windows8、windows10也能完美兼容,在各windows服务器上兼容能力也很强。 6、phpwamp集成环境还能与其他任意环境共存,互不影响,端口号可视化修改,强制解除端口占用等。 7、拥有强制干掉一切环境阻碍,一键强制卸载任意php环境,瞬间轰掉阻碍(不会影响系统),简单粗暴,让你节省时间立刻完成网站配置。 8、切换PHP版本方便,还能自定义PHP版本,提供700个PHP版本随便你换,及时满足各种程序对不同版本的需求。 9、在phpMyAdmin官方网站,你可以看到phpMyAdmin的各个版本下载中都提示了不同版本所能兼容的PHP版本与数据库版本,而PHPWAMP自带的数据库管理工具phpMyAdmin经过特殊修改,能完美兼容任何PHP版本,无论你切换任意PHP版本,都能正常使用,不会像一些PHP环境那样,升级或者换个版本,phpMyAdmin就会出现问题。 10、PHPWAMP拥有自动定期重启动服务器,自动定期重启动apache、mysql等服务的功能。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

草上爬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值