constexpr的奇怪行为

时间:2017-09-22 12:50:37

标签: c++ compiler-optimization constexpr

我试图尽可能地了解constexpr。但是,我发现了一个我无法解释的问题(我不理解编译器对此代码片段的决定)。此代码已在X86-64 gcc 7.2上使用-O3标志进行编译,其中C ++ 17为标准(我已使用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类,它创建一个给定大小的数组,然后将数组与增量值相加(arr [0] = 0,arr [1] = 1,arr [2] = 2 ... arr [n] = n)在compile_time上(至少那就是我想要的)。  如果&#34; NUMBER&#34; define在范围内:{0&lt; = NUM​​BER&lt; = 4或8&lt; = NUM​​BER&lt; = 71} 然后这个类完全优化,只返回一个值(如预期的那样)

然而!如果NUMBER在范围内:{5&lt; = NUM​​BER&lt; = 7或NUMBER&gt; = 72},则编译器ISN可以优化返回值。 怎么会?这些价值观有什么特别之处? 您可以在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)中写什么,它都会显示在编译时优化和计算的值!

1 个答案:

答案 0 :(得分:1)

与您的期望相反,您的课程不是constexpr(并且未在constexpr表达中使用)。

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

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

所以你在装配时观察到的只是定期优化。