【问题标题】:"Safe" way to add an element to a std::vector beyond its size() but under its capacity()将元素添加到 std::vector 超出其 size() 但低于其 capacity() 的“安全”方式
【发布时间】:2017-05-04 20:56:45
【问题描述】:

这听起来可能很危险,但我正在尝试做这样的事情:

std::vector<StructureSlowToBeCreated> vElems;

StructureSlowToBeCreated s1, s2;

vElems.reserve(many_slots_for_structs);

vElems[x1] = s1; // I can ensure x1, x2 < many_slots_for_structs
vElems[x2] = s2;

基本上,这个想法是避免使用

vElems.resize(many_slots_for_structs);

由于 s1s2 的创建速度都很慢,因此我不想做两次。正如我所说,我可以 100% 确保 x1x2 将在向量 容量 边界内,但也有很多次肯定在size 边界(因此,使用 "at()" 会导致异常)。

有没有更清洁的方法来做到这一点?或者我是否应该认为这个足够干净(我感觉它不是)。

我确实需要将 s1 放在 x1 索引处,否则,我需要将 x1 存储为 x1 的参数strong>s1 并存储辅助地图以将 x1 与矢量中 s1 的位置联系起来(我会添加查看地图的成本每次访问 s1s2,我想不惜一切代价避免)。

非常感谢您的帮助。

【问题讨论】:

  • 我认为有很多关于如何使用向量的示例和参考资料。是的,有一个更清洁的方式,因为你的方式是一个错误。
  • 如何使用reservepush_backemplace_back
  • 要么使用emplace_back 以避免无意义的构造,修复你的类以使其构造不会那么慢,或者使用std::vector&lt;std::optional&lt;X&gt;&gt;(或boost::optional)懒惰地构造实际元素。
  • 或者使用地图,或者类似的容器。
  • @NeilButterworth:好点,我错过了一些关于这些需要如何在特定索引上的内容。听起来“嘿,我的容器不支持这个”可能是您使用错误的一个很好的指标。

标签: c++ vector size capacity


【解决方案1】:

您不能访问超出其大小的 std::vector。这似乎可行,但it is UB 最终会产生问题。

执行此任务的正常方法是使用地图,以便您只创建所需的元素。但是,找到第 n 个元素是 O(logn) 而不是 std::vector 的常数时间。

std::map<size_t, StructureSlowToBeCreated> myMap;

如果您确实需要恒定时间访问,则必须调整向量的大小。我知道您不想默认构造所有元素,因为这是一项耗时的操作。然后,您可以创建存储对象的其他元素的 std::vector。例如:

std::vector<std::optional<StrSlowToBeCreated>> myVec; // as suggested by GManNickG
std::vector<std::unique_ptr<StructureSlowToBeCreated>> myVec;

您可能可以根据对象大小在 optional 和 unique_ptr 之间进行选择。

【讨论】:

  • 谢谢,使用 std::optional 的想法看起来优雅而整洁。
  • 是的。 optional 的问题是您需要 C++17 或 boost。此外,可选项的大小大于它包含的对象的大小。使用unique_ptr稍微复杂一些,但是只需要C++11,unique_ptr的大小只有一个指针的大小。
猜你喜欢
  • 2015-10-03
  • 2022-01-19
  • 1970-01-01
  • 2011-03-24
  • 2020-08-19
  • 2012-03-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多