【问题标题】:How to dynamically update the condition of a for loop in C++?如何在 C++ 中动态更新 for 循环的条件?
【发布时间】:2017-07-08 08:15:27
【问题描述】:

取如下代码sn-p:

// x is a global vector object that holds values of type string as follows, vector<string> x
// x is filled/populated via the function Populate_x(y,z);

Populate_x(y,z);

for (auto i : x)
{
string v = check(i);      
Populate_x(v,v);
}

我的问题是,当从 for 循环中调用 Populate_x(v,v) 时,如何在上面显示的基于 for 循环的范围内动态更新 x?我不确定这是否可能。如果没有,我该如何重构我的代码来实现这种行为?

非常感谢您的建议。

【问题讨论】:

  • 也许更完整的示例会有所帮助,但显然您不需要执行相关范围,因此您应该使用其他解决方案,例如传统的 for 循环,但可能是 while 循环。如果没有更完整的示例,很难提供具体的示例代码。

标签: c++ for-loop conditional


【解决方案1】:

基于范围的for 循环大致相当于:1) 获取容器的开始和结束迭代器,2) 使用临时迭代器从开始迭代器值迭代到结束迭代器值 3) 在每次迭代中,取消引用临时迭代器并将范围循环的变量设置为取消引用的迭代器值。

...或多或少。底线是 1)基于范围的 for 循环获取并使用范围的开始和结束迭代器,以及 2)您声明您的容器是一个向量,并且如您所知,修改一个向量将使大多数迭代器都指向向量的内容。

确实,通过对向量内容的某些类型的修改,某些迭代器不会失效,并且将保持有效。但是,实际上,可以安全地假设如果您在某处有 std::vector::iteratorstd::vector::const_iterator,则修改向量意味着迭代器不再有效。正如我所提到的,并不总是 100% 正确,但这是一个非常安全的假设。

并且由于范围迭代获得并使用容器的迭代器,因此在迭代的生命周期内,几乎可以对向量进行范围迭代,并在迭代期间修改向量,这是一个非启动器。对于向量的任何持续迭代,对向量的任何修改都可能导致未定义的行为。

请注意,“修改”本质上是指从向量中插入或删除值;也就是说,修改向量本身。修改向量中的不会影响任何现有迭代器的有效性,这是安全的。

如果您想遍历一个向量,然后在此过程中安全地修改该向量(修改包括从向量中插入或删除值),您必须自己回答的第一个问题是插入或迭代的移除平均值。这是你必须自己弄清楚的事情。例如,如果您的循环当前位于向量中的第 4 个元素上,并且您在向量中插入一个新的第二个值,因为向向量中插入一个值会使向量中的所有剩余值向上移动,则第 4 个元素在vector 将成为向量中的第 5 个元素,如果您设法安全地正确执行此操作,则在下一次迭代中,向量中的第 5 个元素将与您之前迭代的相同。这是你想要的吗?这是您必须首先自己回答的问题。

但就在迭代期间安全地修改向量而言,最简单的方法是完全避免使用迭代器,并使用索引变量:

for (size_t i=0; i<x.size(); ++i)
{
    auto v=x[i];

    // ...
}

现在,修改向量是非常安全的,那么您需要弄清楚的是,在向量被修改之后会发生什么,i 索引变量是否需要调整,以任何方式。

那个问题你必须自己回答。

【讨论】:

  • 感谢 Sam 的详细报道。我同意你的看法。
【解决方案2】:

根据您的描述,我不确定您所说的动态更新 x 是什么意思。

Populate_x 是否向 x 添加新元素?

假设您的 Populate_x 函数尝试 push_back 向量 x 上的某些元素,那么您不能这样做。详情请见this answer

修改循环内的向量会导致未定义的行为,因为循环使用的迭代器在修改向量时无效。

如果是这样,如果你想在 x 的末尾添加多个元素,一个实用的方法是使用一个临时的 vector&lt;string&gt; y;push_back/emplace_back 元素到 y,然后一次您已准备好将y 的所有元素附加到x 中,执行类似于this 的操作(在这种情况下,v1 是您的xv2 是您的y

x.insert(x.end(), make_move_iterator(y.begin()), make_move_iterator(y.end()));

【讨论】:

  • 谢谢文森特!这正是我想要的。而且,你的假设是正确的,我回来推向量 x 上的一些元素。我按照您提出的解决方案的步骤进行操作,但 x 仍然没有在 for 循环中进行更新,尽管通过 Populate_x 函数进行了更新。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-19
  • 2021-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多