【问题标题】:How to make sure the accessed index in a vector exists?如何确保向量中访问的索引存在?
【发布时间】:2014-12-10 18:46:12
【问题描述】:

我有一个文本标签向量std::vector<sf::Text> texts_。我可以像这样创建文本并将它们推送到向量中:

texts_.push_back(utils::createText(x, y, "SomeString1"));
texts_.push_back(utils::createText(x, y, "SomeString2"));
// etc.

然后像这样轻松地绘制它们:

for (std::size_t i = 0; i < texts_.size(); ++i) {
  renderTarget.draw(texts_.at(i));
}

我偶尔想更新文本的字符串。我目前做的是:

texts_.at(0).setString("SomeUniqueString1");
texts_.at(1).setString("SomeUniqueString2");
texts_.at(2).setString("SomeUniqueString3");
// ...

以上所有工作都很好。 现在解决问题:

更新字符串时,如果我不小心尝试访问例如 10 的索引,即使向量中只有 5 个文本,该怎么办?

如果我这样做,程序显然会崩溃。我可以每次检查索引是否小于向量的大小,但这有点矫枉过正(我必须在代码中添加更多检查......)?如何不费吹灰之力确保该索引处的文本存在于向量中?

【问题讨论】:

  • “如果我这样做,程序显然会崩溃。” 不,不是很明显。因为您使用的是v.at(0),所以它会抛出一个异常,您可以适当地捕获和处理它。如果您使用的是v[0],它可能会崩溃(或做一些更糟糕的事情),但vector::at() 会进行范围检查。
  • 如果您不知道向量中的索引在程序中的任何时候是否有效,那是因为您的向量在您保持引用(索引)时发生了变化。这将代表一个设计缺陷——因为依赖对可能不再存在的数据的引用在逻辑上是不正确的。也许是时候重新考虑设计了?或者你有可能是偏执狂吗?它可能有助于分析执行路径。任何改变数据的路径都不应保留引用。
  • 我同意@RichardHodges 的观点,如果您尝试访问 10 的索引,即使向量中只有 5 个元素,这表明存在设计缺陷;您应该重新设计代码以确保向量中始终至少有 10 个元素,或者更好的是,不要对索引值进行硬编码。如果不符合您的要求,您甚至可能想查看其他容器类型(而不是矢量)。

标签: c++ vector sfml assert


【解决方案1】:

如果您需要编写的样板数量让您感到困扰,只需在函数中编写一次即可。

template<class T, typename ValueType>
void SafeSetValue(T & container, size_t index, const ValueType & value)
{
    if (index < container.size())
        container[index] = value;
}

SafeSetValue(texts_, 0, "SomeUniqueString1");

您可以更改函数以在索引越界的情况下执行不同的操作。

【讨论】:

  • 我不喜欢这样:vector::at 已经提供范围检查、有符号/无符号比较、按值复制(消除容器提供的优化),假设运算符 [] 存在。跨度>
  • @DieterLücking 因为at 的边界检查在这个函数中是多余的,我认为使用operator[] 会更好。你可以在自己的代码中使用任何你想要的东西。我没有立即想到我应该通过引用传递字符串,我想稍后进行编辑但决定不这样做。我改变了主意,请稍等,让我知道您对这些变化的看法。
  • @RichardHodges,也许是这样。我试图假设一个问题背后有充分的理由,因为我经常对自己的想象力失败感到惊讶。
  • @MarkRansom 我理解,但在这种情况下,我可以向您保证,该程序在逻辑上是不正确的 :-)
【解决方案2】:

如果我这样做,程序显然会崩溃。我可以每次检查索引是否小于向量的大小,但这有点矫枉过正(我必须在代码中添加更多检查......)?我怎样才能不费吹灰之力地确保该索引处的文本存在于向量中?

如果您使用std::vector&lt;&gt;::at() 访问元素,则正在执行检查。如果索引超出范围,则会抛出异常。 检查其他成员函数(特别是 operator[])。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-02-26
    • 1970-01-01
    • 2012-06-05
    • 1970-01-01
    • 2022-10-15
    • 2020-08-31
    • 2016-08-25
    • 2012-03-19
    相关资源
    最近更新 更多