最终二进制大小: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
函数本身必须不同,但底层存储不是。
首先,我阅读了关于定义 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
函数本身必须不同,但底层存储不是。