Constexpr就是这种正确的行为

Constexpr is this correct behaviour?

本文关键字:Constexpr      更新时间:2023-10-16

我不确定这是正确的行为。所以我之前没有使用过constexpr,我想确保我没有误解规范的某些内容。按照MSDN提到的方式进行测试。如果我在函数中设置了一个断点,它被跳过,那么它在编译时就会被求值。行为不正常吗?

https://msdn.microsoft.com/en-us/library/dn956974.aspx

  1. 它似乎只与优化周期工作。
  2. 只有当我将值设置为constexpr变量或在与输入变量无关的特定用例中才有效。

由于某些原因,这行得通

constexpr unsigned int factorial(unsigned int n)
{
    return n <= 1 ? 1 : n*factorial(n - 1);
}
constexpr unsigned int value = factorial(5);
std::cout << value << std::endl;

但是它会在运行时运行

constexpr unsigned int factorial(unsigned int n)
{
    return n <= 1 ? 1 : n*factorial(n - 1);
}
std::cout << factorial(5) << std::endl;

似乎有点不方便,不得不做一个constexpr变量。它似乎在其他一些特殊情况下也有效。

switch (fnv1a("Hello"))
{
case fnv1a("GoodBye"):
    std::cout << "GoodBye" << std::endl;
    break;
case fnv1a("Hello"):
    std::cout << "Hello" << std::endl;
    break;
default:
    break;
}

此case将case值初始化为常量,但switch语句中的调用不会计算为constexpr,而是在运行时运行。

由于某种原因,相等操作符似乎也是有效的。本例仅为动态值调用一次fnv1a。

void isValue(const char* str)
{
    if (fnv1a(str) == fnv1a("Hello"));
    std::cout << "Found it!" << std::endl;
}

我知道MSVC在遵从性方面有一些问题,但是基于用例而不是输入常量的行为对我来说似乎很奇怪。

您观察到的行为是正确的。constexpr函数只需要在编译时对常量表达式调用。这包括constexpr函数的返回值用作constexpr变量的初始化项,或用作非类型模板形参的值的情况。

在所有其他情况下,编译器不需要在编译时对函数求值。