C++11:constexer 的用法详解


引入

C++11 为了提高代码执行效率做了一些改善。这种改善之一就是:生成常量表达式,允许程序利用编译时的计算能力。 假如你熟悉模板元编程,你将发现 constexpr 使这一切变得更加简单。constexpr 使我们很容易利用上编译时编程的优势。

常量表达式主要是允许一些计算发生在编译时,即发生在代码编译而不是运行的时候。这是很大的优化:假如有些事情可以在编译时做,它将只做一次,而不是每次程序运行时。

需要计算一个编译时已知的常量,比如特定值的 sine 或 cosin ?确实你亦可以使用库函数 sin 或 cos,但那样你必须花费运行时的开销。使用 constexpr,你可以创建一个编译时的函数,它将为你计算出你需要的数值,用户的电脑将不需要做这些工作。

constexpr 初识

为了使函数获取编译时计算的能力,你必须指定 constexpr 关键字到这个函数。

constexpr int multiply (int x, int y)
{
    return x * y;
}

// 将在编译时计算
const int val = multiply( 10, 10 );

除了编译时计算的性能优化,constexpr 的另外一个优势是,它允许函数被应用在以前调用宏的所有场合。

例如,你想要一个计算数组 size 的函数,size 是 10 的倍数。如果不用 constexpr,你需要创建一个宏或者使用模板,因为你不能用函数的返回值去声明数组的大小。但是用 constexpr,你就可以调用一个 constexpr 函数去声明一个数组。

constexpr int getDefaultArraySize (int multiplier)
{
    return 10 * multiplier;
}

int my_array[getDefaultArraySize(3)];
int a = 4;  //非常量表达式
getDefaultArraySize(a);  //ok

constexpr 修饰的函数,简单的来说,如果其传入的参数可以在编译时期计算出来,那么这个函数就会产生编译时期的值。但是,传入的参数如果不能在编译时期计算出来,那么 constexpr 修饰的函数就和普通函数一样了。 不过,我们不必因此而写两个版本,所以如果函数体适用于 constexpr 函数的条件,可以尽量加上 constexpr。

constexpr 修饰函数的限制

一个 constexpr 有一些必须遵循的严格要求:

  • 函数中只能有一个 return 语句(但允许包含 typedefs、 using declaration && directives、静态断言等)
  • 函数必须有返回值(即不能式void函数)
  • 只能调用其它 constexpr 函数
  • 只能使用全局 constexpr 变量

注意递归并不受限制,但只允许一个返回语句,那如何实现递归呢?可以使用三元运算符( ? : )。例如,计算n的阶乘:

constexpr int factorial (int n) {
    return n > 0 ? n * factorial( n - 1 ) : 1;
}

现在你可以使用 factorial(2),编译器将在编译时计算这个值,这种方式运行更巧妙的计算,与内联截然不同。你无法内联一个递归函数。

constexpr vs const 的区别

假如你将一个成员函数标记为 constexpr,则顺带也将它标记为了 const。如果你将一个变量标记为 constexpr,则同样它是 const 的。但相反并不成立,一个 const 的变量或函数,并不是 constexpr 的。

语义上:

  • constexpr:告诉编译器我可以是编译期间可知的,尽情的优化我吧。
  • const:告诉程序员没人动得了我,放心的把我传出去;或者放心的把变量交给我,我啥也不动就瞅瞅。

语法上:

  • constexpr 是一种比 const 更严格的束缚,它修饰的表达式本身在编译期间可知,并且编译器会尽可能的 evaluate at compile time。在constexpr 出现之前,可以在编译期初始化的const都是implicit constexpr。直到 C++ 11,constexpr 才从 const 中细分出来成为一个关键字,而 const 从 1983 年 C++ 刚改名的时候就存在了… 如果你初学 C++, 应当尽可能的,合理的使用 constexpr 来帮助编译器优化代码。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值