康特斯普的奇怪行为
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();
会向您显示您遇到的不同错误。
因此,您在汇编中观察到的只是常规优化。
相关文章:
- 康斯特指针C++斯特劳斯特鲁普
- Static_cast 对于康斯特来说,会抛弃预选赛
- 东康斯泰克普/康斯蒂尼特/康斯特瓦尔在C++20 中允许吗?
- 康斯坦特还行,但不是康特克斯普尔?
- 康斯特正确性建议
- 吉特斯和塞特斯与FRIEND_TEST
- 从字符到康斯特* 字符的转换无效,代码有什么问题?
- T*上的部分排序...和康斯特·
- integral_constant vs 康特斯普尔
- 康特斯普的奇怪行为
- 调用"树:<int>:运算符==(树*&<int><int>,树*&)康斯特"没有匹配函数
- 常量与变量上的常量与康特克斯PR
- 抛弃康斯特,就是这种定义明确的行为
- 错误:类型为 '.&' 来自类型的临时 '..*康斯特'
- 如果我将类声明为常量,程序不起作用...而不是康特斯普?
- 无法push_back移动(不可复制与康斯特字段)到矢量
- 传递康斯特字符*的值
- mpg123_open()和康斯特
- 康斯特指针浅拷贝
- C++ wifstream:不兼容的字符常量*,wchar_t康斯特*类型