我有一个四/八叉树的数据结构.我将一个单元格的子索引/ ptrs存储在数组中.阵列中的每个位置表示一个孩子相对于其父母的位置,例如,在2D中:
// _____________ // | | | // | 2 | 3 | // |_____|_____| // | | | // | 0 | 1 | // |_____|_____| // for each cell,4 children are always stored in row-major order std::vector<std::array<Integer,4>> children;
我知道最大数量的孩子是Integer类型可以表示的值的一个子集.因此,通过使用Integer = int或Integer = unsigned的std :: numeric_limits< unsigned> :: max(),可以识别单元格是否缺少一个小孩.这是std :: optional< Integer>不能假设
据我所知,魔术值的使用是std :: optional的存在理由之一.不过,我担心std :: vector< std :: optional< int>>的性能.在内圈.
所以,
>将会执行std :: vector< std :: optional< int>>比std :: vector< int> (我已经在比较“不存在”的价值).
>或者,可以优化std :: optional的实现来提供与raw int相同的性能吗?如何?
在我的数据结构中,我的函数和魔术值的返回类型混合std :: optional听起来是一个非常糟糕的主意.我更喜欢保持一致,并且使用一个或另一个(至少在同一个上下文中).虽然我可以重载与魔术数字进行比较的功能:
template<T> bool is_valid(const T& t) { return /* comparison with magic value for t */; }
用于可选类型.
解决方法
std :: optional将需要额外的存储空间,并将较少的值安装到缓存中(看来您已经知道了这个原因).
只要内部表示完全被用户隐藏,我们认为在公开API公开的数据结构中内部存储不同的值不是错误的.
此外,我建议您将魔术数字隔离成一对内联转换功能.
编译器应该帮助您记住一直使用转换函数,如果您忘记了生成类型错误.您甚至可以在内部数据结构中为int使用精简的struct wrapper,以确保不存在隐式转换(或定义用户定义的转换).
class CompressedOptionalUInt { static const unsigned SENTINEL_MISSING = std::numeric_limits<unsigned>::max(); unsigned value; public: CompressedOptionalUInt(std::optional<unsigned> val) : value(!val? SENTINEL_MISSING: *val) {} operator std::optional<unsigned>() const { ... } };
然后使用std :: array< CompressedOptionalUInt> ;. 把它放在模板中,只需要为每个类型定义哨兵,应该是非常简单的.