C++中替代C嵌套数组指定初始化实现二维数组的最优方案是什么
C++ 兼顾可读性与编译期性能的二维数组初始化方案
方案1:使用C++20指定初始化(最接近C原生写法)
C++20正式引入了指定初始化语法,只要初始化顺序和枚举/数组元素的声明顺序完全匹配,就可以合法使用,写法和原C代码几乎一致,完全保留可读性,同时是编译期静态初始化:
#define NUMBER_OF_TOKEN_KINDS 15 enum TokenKind { Literal, Alternator, // 其余枚举值按原顺序定义 }; class Lexer { private: static constexpr bool m_grammar_allowed[NUMBER_OF_TOKEN_KINDS][NUMBER_OF_TOKEN_KINDS] = { // 其余行按枚举定义顺序填写 [Literal] = {[Alternator] = true}, [Alternator] = {[Literal] = true}, // 其余规则按顺序补充 }; };
注意C++20要求同一层级的指定初始化器必须和声明顺序一致,只要枚举的定义顺序不变,就可以正常使用。
方案2:C++11及以上兼容的constexpr生成函数(兼容性最好)
如果需要兼容旧标准,可以写一个constexpr静态函数生成数组,在函数内按下标赋值方式写规则,返回值直接用来初始化静态constexpr数组,整个过程完全在编译期完成,不会产生运行时开销,可读性和构造函数赋值的写法完全一致:
#define NUMBER_OF_TOKEN_KINDS 15 enum TokenKind { Literal, Alternator, // 其余枚举值定义 }; class Lexer { private: static constexpr auto build_grammar_allowed() { bool arr[NUMBER_OF_TOKEN_KINDS][NUMBER_OF_TOKEN_KINDS] = {}; // 初始全为false // 直接按规则赋值,和运行时写法完全一致 arr[Literal][Alternator] = true; arr[Alternator][Literal] = true; // 其余规则补充 return arr; } static constexpr bool m_grammar_allowed[NUMBER_OF_TOKEN_KINDS][NUMBER_OF_TOKEN_KINDS] = build_grammar_allowed(); };
该方案兼容性最好,C14及以上可以直接使用,C11仅需调整返回值写法即可适配,所有初始化逻辑都在编译期执行,最终数组会直接固化到可执行文件的只读段,性能和C原生的静态初始化完全一致。
方案3:位域压缩优化(可选,性能更高)
如果TokenKind数量不超过64,还可以用std::bitset或者整数类型把每一行的规则压缩成单个数值,初始化时直接给每行赋值对应的位掩码,可读性也很高:
#include <bitset> class Lexer { private: static constexpr std::bitset<NUMBER_OF_TOKEN_KINDS> m_grammar_allowed[NUMBER_OF_TOKEN_KINDS] = { [Literal] = 1 << Alternator, // 等价于Literal后面可以接Alternator [Alternator] = 1 << Literal, // 其余规则补充 }; };
检查规则时直接用m_grammar_allowed[previous].test(current)即可,内存占用比bool二维数组小很多,检查速度也更快。
内容的提问来源于stack exchange,提问作者Joku
相关产品推荐
相关产品推荐

