康特斯普的奇怪行为

strange behavior of constexpr

本文关键字:康特斯      更新时间:2023-10-16

我正在尽我所能地理解constexpr。但是,我发现了一个我无法真正解释的问题(我不理解编译器对此代码片段的决定)。这段代码是在 X86-64 gcc 7.2 上使用 -O3 标志编译的,其中 C++17 是 std 标志(我一直在使用此编译 godbolt.org)

获取此代码:

#include <stdlib.h>
#include <stdio.h>
template <size_t N>
class constexpr_sum_array_compile_time
{
public:
inline constexpr constexpr_sum_array_compile_time ()
{
start_arr();
sum();
}
inline constexpr void start_arr()
{
for (int i = 0; i<N; ++i)
{
m_arr[i] = i;
}
}
inline constexpr void sum()
{
m_sum = 0;
for (int i = 0; i<N; ++i)
{
m_sum += m_arr[i];
}
}
constexpr int sum_res()
{
return this->m_sum;
}
private:
int m_arr[N];
int m_sum = 0;
};
#define NUMBER (4)
int main()
{
return constexpr_sum_array_compile_time<NUMBER>().sum_res();
}

简而言之,这是一个 constexpr 类,它创建一个具有给定大小的数组,然后在compile_time上对一个具有增量值的数组求和(arr[0] = 0, arr[1] = 1, arr[2] = 2... arr[n] = n)(至少我希望它这样做)。 如果"数字"定义在范围内:{ 0 <= 数字 <= 4 或 8 <= 数字 <= 71 } 然后这个类被完全优化,只返回一个值(如预期)

然而!如果 NUMBER 在 { 5 <= NUMBER <= 7 或 NUMBER>= 72} 范围内,则编译器无法优化返回值。 怎么来了?这些价值观有什么特别之处? 您可以在 godbolt.org 检查优化,它在编译时显示原始程序集。

解决

似乎我需要创建一个包含 constexpr 关键字的变量,以便编译器在编译时计算它。新代码为:

#include <stdlib.h>
#include <stdio.h>
template <size_t N>
class constexpr_sum_array_compile_time
{
public:
inline constexpr constexpr_sum_array_compile_time() : m_arr(), m_sum(0)
{
start_arr();
sum();
}
inline constexpr void start_arr()
{
for (int i = 0; i<N; ++i)
{
m_arr[i] = i;
}
}
inline constexpr void sum()
{
m_sum = 0;
for (int i = 0; i<N; ++i)
{
m_sum += m_arr[i];
}
}
inline constexpr int sum_res()
{
return this->m_sum;
}
private:
int m_arr[N];
int m_sum;
};
#define NUMBER (6)
int main()
{
constexpr auto res = constexpr_sum_array_compile_time<NUMBER>().sum_res();
return res;
}

现在,无论我在 NUMBER 中写什么(甚至是 100000),它都会显示编译时优化和计算的值!

与你的期望相反,你的类不是constexpr的(也不用于constexpr表达式)。

constexpr auto res = constexpr_sum_array_compile_time<NUMBER>().sum_res();

会向您显示您遇到的不同错误。

因此,您在汇编中观察到的只是常规优化。