2017-02-18 116 views
1

采取下面的代码片断:如何在C++中动态更新for循环的条件?

// 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); 
} 

我的问题是,如何才能动态调用Populate_x(V,V)时从内部for循环更新如上所示在基于for循环范围X?我不确定这是否可能。如果不是,我如何重构我的代码来实现这种行为?

您的建议非常感谢。

+0

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

回答

3

一系列基d for loop等价于:1)获取容器的开始和结束迭代器,2)使用临时迭代器从开始迭代器值迭代到结束迭代器值3)在每​​次迭代中,解引用临时迭代器并设置范围循环的变量到解除引用的迭代器值。

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

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

而且由于范围迭代获取并使用容器的迭代器,因此在迭代的整个生命周期中,它几乎都会对向量执行范围迭代,并在迭代过程中修改向量,这是非启动器。对向量的任何修改都可能导致未定义的行为,对于向量的任何持续迭代。请注意,“修饰”实质上是指插入或去除向量中的值;即矢量本身的修改。在向量中修改对任何现有迭代器的有效性都没有影响,这是安全的。

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

但据安全改进迭代过程中的载体,最简单的方法是避免使用迭代器完全和使用索引变量:

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

    // ... 
} 

现在,修改矢量是完全安全的,并且所有你必须弄清楚,那么之后矢量被修改后,i索引变量是否需要以任何方式进行调整。

问题你必须回答自己。

+0

感谢Sam的详细报道。我赞同你。 – Xigma

+0

您提出的解决方案有效。我现在明白了为什么。 – Xigma

1

从您的描述中,我不确定动态更新x是什么意思。

是Populate_x 新元素x?

假设您的Populate_x函数尝试push_back向量x上的某些元素,那么您不能这样做。有关详细信息,

修改未定义行为的循环结果里面的载体,因为当载体被修改通过循环使用的迭代器失效见this answer

如果是这样,如果你想在x末尾添加多个元素,实用的方法是使用临时vector<string> 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())); 
+0

谢谢文森特!这正是我想要的。而且,你的假设是正确的,我回推了向量x上的一些元素。我按照您提出的解决方案执行了这些步骤,但尽管通过Populate_x函数进行了更新,x仍然没有在for循环中进行更新。 – Xigma