【发布时间】:2012-07-04 19:01:06
【问题描述】:
我目前正在改变我访问数据结构的方式,并且我正在审查向量向量的一般情况下的两种解决方案之一。
我的动机很简单;我想要缓存局部性而不放弃我的接口。
我知道我的向量在编译时的最大大小,但它们并不总是达到最大值。常见的情况是80%左右,每个向量的总大小要比较小。 如果我达到那个最大值,我在某处的逻辑上犯了错误,并希望它抛出一个错误。
想到的第一个解决方案是使用带有 std::vector 的池分配器,这似乎是个好主意,但可能有点混乱;之前没有正确使用分配器,我不太确定解决方案。我不太喜欢将数据与其所有者分开存储,我希望实现尽可能透明。
目前,第二种解决方案对我来说很有效,但我想让它变得不那么符合要求。目前是这样的:
class Foo {
public:
std::array<Bar, 10> bars;
size_t used;
// std::vector<Bar> bars; // reserved to 10... maybe
void add(int var1, int var2) {
if (used >= bars.size()) throw "Error";
bars[used] = Bar(var1, var2);
++used;
// std::vector alternative
// bars.push_back(Bar(var1, var2));
}
void remove(size_t idx) {
bars[idx] = bars.back();
--used;
// bars.back().~Bar(); // should happen, not sure if safe
// std::vector alternative
// bars[idx] = bars.back();
// bars.pop_back();
}
}
如前所述,效果很好。但是,如果我想将此解决方案移到其他地方,我宁愿不必再次实现它,并且在破坏方面具有适当的语义(类似于 actual 向量的语义)。
那么,我想知道什么是好的解决方案?目前,我已经开始包装std::array,但它开始变得凌乱,我确信这已经解决了问题。
【问题讨论】:
-
通过让你的接口采用一个它们无法添加的向量,你破坏了它们。他们首先不应该采用向量,而是采用数组。还是我错过了什么?
-
目前,我使用的是
std::vector,并保留了必要的空间。关键是他们可以随意添加/删除,但不应永远不要超过最大限制。目前这并没有严格执行,因为它并不重要,它只是我可以利用的东西。 -
所以我猜“改变你的界面”不是一个理想的解决方案?
-
@Oli Charlesworth,鉴于当前解决方案之间的切换工作只是从
std::vector更改为std::array并添加使用的元素数量;我希望不必再做任何事情;但是如果我以后想在其他地方做这件事,这将是一笔巨大的财富;正如我所知道的许多情况下,我知道运行时的最大大小,想要向量的灵活性,但需要数组的局部性(特别是如果封装在一个对象中,在经常迭代的 1000 个对象中,如果分配了缓存,则在其中颠簸无处不在)。 -
您可以使用
decltype;这是包装模板的明智风格。您对throw的使用有问题;你肯定可以抛出适当的异常吗?您调用的析构函数 (this->back().~T();) 错误;您应该将元素保持在有效状态并使用this->back() = T()重置为默认初始化状态。