最终二进制大小:constexpr 变量与 constexpr 函数

Final binary size: constexpr variable vs constexpr function

首先,我阅读了关于定义 constexpr 变量与 constexpr 函数之间的文体差异的非常有用的 answer。我的问题与使用这两个时二进制文件的最终大小更相关。考虑这段代码:

// approach 1
template <typename T>
struct foo
{
  static constexpr char name[] = "mickey";
};

// approach 2
template <typename T>
struct bar
{
  static constexpr const char* getName() { return "mickey"; }
};

const char* func1() { return foo<int>::name; }
const char* func2() { return foo<double>::name; }

const char* func3() { return bar<int>::getName(); }
const char* func4() { return bar<double>::getName(); }

也请查看此 godbolt link 中的代码。虽然方法 1 returns 名称的不同副本,但方法 2 returns 对于不同 T 的所有不同实例化只有一个副本。事实上,当我创建 100 种不同类型时,方法 2 导致了一个相当小的二进制文件。想知道有没有人经历过类似的事情。

嗯,这两种方法实际上并不相同。有些事情你可以用 foo<T>::name 做而你不能用 bar<T>::getName() 做:我可以指向它,我可以引用它。该能力可防止不同的 foo<T>::name 相同。

但是 getName() 就没有这样的问题了。你只是得到一个纯右值——你不能获取它的地址。不同的 bar<T>::getName 函数本身必须不同,但底层存储不是。