也许已经有人问过类似的问题,当然,这是一个吹毛求疵...
我有一堆常量 std::map
用于在 enum (class)
值和它们的 std::string
表示之间切换(双向)。这里有人向我指出,这些映射将在运行时初始化,当其他初始化代码运行时,在我的程序执行所有好东西之前。这意味着常量表达式会影响运行时性能,因为映射是根据它们的枚举字符串对构建的。
作为说明性示例,这里是其中一张 map 的示例:
enum class os
{
Windows,
Linux,
MacOSX
};
const map<string, os> os_map =
{ {"windows", os::Windows},
{"linux", os::Linux},
{"mac", os::MacOSX} };
const map<os, string> os_map_inverse =
{ {os::Windows, "windows"},
{os::Linux, "linux"},
{os::MacOSX, "mac"} };
C++11 constexpr
是否会对性能产生任何影响,或者我对运行时初始化惩罚的假设是否错误?我认为编译器可以将常量 STL 容器作为纯数据嵌入可执行文件中,但显然这可能不像我说的那么容易?
最佳答案
问题与其说是初始化的性能,不如说是初始化的顺序。如果有人在 main
开始之前使用你的 map (例如在命名空间范围变量的初始化时),那么你就是 SOL,因为你不能保证你的 map 在用户初始化使用它之前已经初始化.
但是您可以在编译时做这件事。字符串文字是常量表达式,枚举数也是如此。一个简单的线性时间复杂度结构
struct entry {
char const *name;
os value;
};
constexpr entry map[] = {
{ "windows", os::Windows },
{ "linux", os::Linux },
{ "mac", os::Mac }
};
constexpr bool same(char const *x, char const *y) {
return !*x && !*y ? true : (*x == *y && same(x+1, y+1));
}
constexpr os value(char const *name, entry const *entries) {
return same(entries->name, name) ? entries->value : value(name, entries+1);
}
如果您在常量表达式上下文中使用 value(a, b)
,并且您指定的名称不存在,您将收到编译时错误,因为函数调用将变成非持续的。
要在非常量表达式上下文中使用 value(a, b)
,您最好添加安全功能,例如向数组添加结束标记并在 value< 中抛出异常
如果你击中了结束标记(只要你从未击中结束标记,函数调用仍将是一个常量表达式)。
关于c++ - constexpr 和初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8026906/