C ++ constexpr-值可以在编译时评估吗?

时间:2018-09-10 18:50:06

标签: c++ c++11

我正在阅读有关constexpr here的信息:

  

constexpr说明符声明可以在编译时评估函数或变量的值。

当我第一次读到这句话时,对我来说这很有意义。但是,最近我遇到了一些使我完全失望的代码。我在下面重建了一个简单的例子:

#include <iostream>

void MysteryFunction(int *p);

constexpr int PlusOne(int input) {
  return input + 1;
}

int main() {
  int i = 0;
  MysteryFunction(&i);
  std::cout << PlusOne(i) << std::endl;

  return 0;
}

看这段代码,我没有办法说PlusOne(i)的结果应该是什么,但是实际上它可以编译! (当然,链接将失败,但是g++ -std=c++11 -c成功,而不会出现错误。)

“可能在编译时评估函数值”的正确解释是什么?

4 个答案:

答案 0 :(得分:11)

在满足常量表达式求值的其他要求的情况下,可以在常量表达式中调用constexpr函数 。它也可以在不是常量表达式的表达式中调用,在这种情况下,其行为与未使用constexpr声明的行为相同。如您问题中的代码所示,调用constexpr函数的结果不是自动一个常量表达式。

答案 1 :(得分:8)

在某种意义上,引用的措词有点误导。如果仅将PlusOne隔离起来,观察其逻辑,并假设输入在编译时是已知的,则其中的计算也可以在编译时执行。在其上拍上constexpr关键字可确保我们保持这种可爱的状态并且一切正常。

但是,如果在编译时不知道输入 ,那么它仍然只是一个普通函数,将在运行时被调用。

因此constexpr是该函数的属性(“对于某些输入不是所有输入的”可能在编译时求值” )您在这种情况下的功能/输入组合(因此对于该特定输入也不是 )。

这有点像一个函数如何使用const int&,但这并不意味着原始对象必须const。这里,类似地,constexpr在函数上添加了约束,而在函数的输入上没有添加约束。

诚然,这都是一个巨大的,令人困惑的,模糊的混乱(C ++!是的!)。请记住,您的代码描述了程序的含义!在编译的不同阶段,这不是机器指令的直接配方。

(要真正执行此操作,您可以将整数作为模板参数。)

答案 2 :(得分:7)

  

“可能在编译时评估函数值”的正确解释是什么?

如果在编译时可以评估函数的所有参数,则可以在编译时评估函数的返回值。

但是,如果仅在运行时知道函数参数的值,则只能在运行时评估函数的retun值。

因此,可能在编译时评估函数的值,但这不是必需的。

答案 3 :(得分:4)

所有答案都是正确的,但我想举一个简短的例子,用来解释constexpr多么荒谬,不直观。

#include <cstdlib>
constexpr int fun(int i){
    if (i==42){
        return 47;
    } else {
        return rand();
    }
}

int main()
{ 
    int arr[fun(42)];
}

请注意: 有些人认为constexpr的状态不令人满意,因此他们提议在语言中添加constexpr!关键字。