constexpr 值是否会导致二进制大小增加?

Sea*_*ean 1 c++ templates constexpr

我知道如下所示的模板化类型不会对编译的二进制大小产生任何影响:

template<auto value>
struct ValueHolder{};
Run Code Online (Sandbox Code Playgroud)

我正在制作一个程序,它将使用很多此类包装类型,并且我认为我不想integral_constant因为这个原因而使用 s ,因为它们有一个::value成员。我可以摆脱类似的事情:

template<typename ValHolder>
struct Deducer;

template<auto value>
struct Deducer<ValueHolder<value>> {
    using Output = ValueHolder<value+1>;
};
Run Code Online (Sandbox Code Playgroud)

但这肯定需要更多的工作,所以我想确保我不会白做。请注意,我们正在谈论大量这样的值(我会解释,但我不想离题太远;我可能会得到更多关于“我应该做这个项目”的评论而不是问题!) 。

所以问题是: [static] constexpr 值在编译的二进制文件中是否采用任何大小,或者这些值是否在编译时被替换,就好像它们是按字面输入的一样?我很确定它们确实会占用二进制文件的大小,但我并不肯定。

我做了一些测试来godbolt并排查看 constexpr 与非 constexpr 数组的组装,一切看起来都与我非常相似: https: //godbolt.org/z/9hecfq

int main()
{
    // Non-constexpr large array
    size_t arr[0xFFFF] = {};

    // Constexpr large array
    constexpr size_t cArr[0xFFF] = {};

    // Just to avoid unused variable optimizations / warnings
    cout << arr[0] << cArr[0] << endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Nic*_*las 6

这完全取决于:

  1. 编译器有多想优化变量。
  2. 如何使用变量。

考虑您发布的代码。您创建了一个constexpr数组。由于这是一个数组,因此使用运行时值对其进行索引是 100% 合法的。这将要求编译器发出访问该索引处的数组的代码,这将要求该数组实际存在于内存中。所以如果你这么使用的话,它就必须有存储空间。

但是,由于您的代码仅使用常量表达式索引来索引该数组,因此想要考虑更多的编译器-O0会意识到它知道该数组中所有元素的值。所以它确切地知道是什么cArr[0]。这意味着编译器可以将该表达式转换为正确的值,并忽略它的cArr存在。

这样的编译器可以对 做同样的事情arr,顺便说一句;它不必是编译器检测无操作的常量表达式。

另请注意,由于两个数组都是非静态的,因此它们都不会占用“已编译的二进制文件”中的存储空间。如果需要它们的运行时存储,则它将是堆栈空间,而不是可执行空间。

一般来说,如果您执行constexpr的操作需要变量占用存储空间,则该变量将在任何合理的优化级别上占用存储空间。这可能与将其传递给接受参数 by 的(非内联)函数一样无害。const&