在编译时知道是什么意思?常数表达式

时间:2018-10-10 00:30:43

标签: c++ c++11 const constexpr

我对在编译时知道它的含义感到困惑。从下面的代码中,即使我已将常量文字值90作为参数传递,编译器是否也无法计算n的值?为什么给我一个错误,就是表达式必须具有常数值

constexpr int MAX_expr = 100;
const int MAX = 90;


void foo(int n)
{
    constexpr int cExpr1 = MAX_expr + 7;
    constexpr int cExpr2 = n + 7;

    constexpr int cExpr1 = MAX + 7;
    constexpr int cExpr2 = n + 7;

    const int cExpr1 = MAX_expr + 7;
    const int cExpr2 = n + 7; 

    const int cExpr1 = MAX + 7;
    const int cExpr2 = n + 7;
}

int main() {
    foo(90);
    const int i = factorials(90);
}

使用相同的逻辑,阶乘(int i)是否不应给出错误,因为它不知道将传递什么参数,因此,编译器将无法计算将要返回的内容? / p>

constexpr int factorials(int i) { 
    return i > 1 ? i * factorials(i - 1) : 1; 
    }

1 个答案:

答案 0 :(得分:3)

constexpr关键字可能令人困惑。它可以应用于变量和函数,但是含义完全不同,除了它们都与常量表达式有关。

constexpr声明的变量必须由常量表达式初始化。在您的代码中,n + 7不是常数表达式,因为n的值直到函数被调用之前才知道,并且每次调用之间可能有所不同。如果用户输入了某个整数,然后又将该整数传递给foo,该怎么办?显然,该数字加7不能称为“编译时已知”。因此,不允许使用诸如foo之类的函数定义。您不能向编译器保证只能传递一个常量表达式参数。如果可以的话,然后将n提升为模板参数,代码将起作用。

相反,应用于函数的constexpr不能保证调用该函数会产生一个常量表达式。它允许在常量表达式中调用该函数,并在定义上施加约束以使其成为可能。如果给定一个运行时参数,factorial当然不会产生一个常数表达式,但是如果给定一个整数常数表达式作为参数,它将产生一个常数表达式(假设没有溢出)。因此,与constexpr变量的初始化程序不同,constexpr函数被允许包含可能具有或可能不具有编译时常数值的构造。