【发布时间】:2013-06-26 15:27:44
【问题描述】:
我有一个四/八叉树数据结构。我将一个单元格的子索引/ptrs 存储在一个数组中。数组中的每个位置都代表一个孩子相对于其父母的位置,例如二维:
// _____________
// | | |
// | 2 | 3 |
// |_____|_____|
// | | |
// | 0 | 1 |
// |_____|_____|
// for each cell, 4 children are always stored in row-major order
std::vector<std::array<Integer,4>> children;
我知道最大子节点数是 Integer 类型可以表示的值的子集。因此,我可以通过使用像-1 表示Integer = int 或std::numeric_limits<unsigned>::max() 表示Integer = unsigned 的“魔法”值来识别单元格是否缺少孩子。这是std::optional<Integer> 无法假设的。
据我所知,魔法值的这种用法是std::optional 存在的理由之一。尽管如此,我还是担心std::vector<std::optional<int>> 在内部循环中的性能。
所以,
std::vector<std::optional<int>>的性能会比std::vector<int>差吗? (我已经在比较“不存在”的值了)。或者,可以优化
std::optional的实现以提供与原始int相同的性能吗?以及如何?
在我的函数的返回类型和我的数据结构中的魔法值中混合std::optional 听起来是个非常糟糕的主意。我更喜欢保持一致并使用其中一个(至少在相同的上下文中)。虽然我可以重载执行与幻数比较的函数:
template<T> bool is_valid(const T& t) {
return /* comparison with magic value for t */;
}
对于可选类型。
【问题讨论】:
-
不确定两者之间的表现,这是您必须自己看到的。不过,问题是,使用比特信息对您来说可行吗?由于您正在存储索引,您可以在单个 int 中编码有关 4 个子索引的信息吗?由于您有 4 个孩子,您可以为每个孩子使用 4 个字节(或更多),这使得 16 个字节总共用于 indeces,而另外 16 个您可以使用它来编码它是否处于活动状态?创建一个类来处理这个问题,这样用户就不必担心内部问题
-
std::optional的存在理由恰恰是您没有具有哨兵价值的情况。如果你有一个“明显”的哨兵,你为什么不使用它? -
@user814628 每个索引都是一个无符号长长...我有很多单元格,无法执行您的建议。
-
@AndréCaron:这将使代码更清晰(更清晰地表达意图)。事实上,如果您可以为用户定义的类型声明一个标记值并告诉
optional使用它,那将是很好的。您甚至可以将std::optional<yourtype>设为好友,将该标记值的构造设为私有。 -
如果您使用
vector<compact_optional<int>>,您将获得类型安全和零性能开销。试试看:github.com/akrzemi1/compact_optional
标签: c++ performance optional c++14 boost-optional