constexpr和初始化

rub*_*nvb 10 c++ initialization const c++11

也许已经有人问过类似的东西,当然,这是一个挑剔......

我有一堆常量std::map来在enum (class)值和它们的std::string表示之间切换(两种方式).这里的某个人向我指出,在我的程序执行所有好东西之前,运行其他初始化代码时,这些映射将在运行时初始化.这意味着常量表达式会影响运行时性能,因为映射是从它们的枚举字符串对构建的.

作为说明性示例,以下是其中一个地图的示例:

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"} };
Run Code Online (Sandbox Code Playgroud)

C++ 11 constexpr会对性能产生任何影响,还是假设运行时初始化惩罚错误?我认为编译器可以在可执行文件中嵌入一个常量STL容器作为纯数据,但显然这可能不像我说的那么简单?

Joh*_*itb 18

初始化的性能不是一个问题,而是初始化的顺序.如果某人在main开始之前使用了您的地图(例如在初始化命名空间范围变量时),那么您就是SOL,因为您不能保证在用户初始化之前已经初始化了地图.

但是你可以在编译时做这件事.字符串文字是常量表达式,枚举数也是如此.简单的线性时间复杂度结构

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);
}
Run Code Online (Sandbox Code Playgroud)

如果value(a, b)在常量表达式上下文中使用,并且指定的名称不存在,则会出现编译时错误,因为函数调用将变为非常量.

value(a, b)在非常量表达式上下文中使用,最好添加安全功能,例如在数组中添加结束标记,value如果点击结束标记则抛出异常(只要你从不,函数调用仍然是一个常量表达式击中结束标记).