在迭代时附加到向量?

JRM*_*JRM 23 c++ stl

我有一个迭代的矢量.在迭代时,我可能会向向量添加新值.它看起来像:

struct Foo
{
   bool condition;
};

void AppendToVec(vector<Foo>& v)
{
   ...
   v.push_back(...);
}

vector<Foo> vec;
...
for (vector<Foo>::size_type i = 0; i < vec.size(); ++i)
{
   if (vec[i].condition) AppendToVec(vec);
}
Run Code Online (Sandbox Code Playgroud)

这样工作正常,事实上优雅地处理新附加元素递归需要添加更多元素的情况,但感觉有点脆弱.如果其他人出现并调整循环,它很容易被破坏.例如:

//No longer iterates over newly appended elements
vector<Foo>::size_type size = vec.size();
for (vector<Foo>::size_type i = 0; i < size; ++i)
{
   if (vec[i].condition) AppendToVec(vec);
}
Run Code Online (Sandbox Code Playgroud)

要么

//Vector resize may invalidate iterators
for (vector<Foo>::iterator i = vec.begin(); i != vec.end(); ++i)
{
   if (vec->condition) AppendToVec(vec);
}
Run Code Online (Sandbox Code Playgroud)

有没有最好的做法来处理这样的案件?用循环注释"警告:迭代时这个循环是故意附加到向量.谨慎改变"最好的方法?如果能让事情变得更加强大,我也愿意切换容器.

Kri*_*son 20

我解决这个问题的方法通常是创建一个我添加任何新元素的队列,然后在迭代原始容器之后,处理队列中的元素和/或将它们附加到原始元素.

这种方法的优点是,正在发生的事情是显而易见的,并且它适用于多个线程可以将新元素排入队列的情况.


sbi*_*sbi 13

如果其他人出现并调整循环,它很容易被破坏.

然后不要使用for循环,while而是使用循环.对我来说,一个for循环总是意味着使用一个简单的计时器,迭代循环.但是,如果我遇到一个while循环,我觉得事情一定是太复杂了,无法在一个简单的for循环中表达它们.我会仔细观察,我对"优化" while循环比使用for循环要小心.

  • +1.我想补充评论"大小()可能会在循环改变,所以不要缓存它"的同时上面的线,来解释为什么一个简单的不会做. (3认同)

Jac*_*cob 5

允许AppendToVec更新i是否vec已使用旧向量(i-vec.begin())中的相对位置重新分配.

码:

void AppendToVec(vector<int> & vec, vector<int>::iterator & i)
{
    const int some_num = 1;
    const size_t diff = i-vec.begin();
    vec.push_back(some_num);
    i = vec.begin()+diff;
}

int main(int argc, char* argv[])
{    
     const size_t arbit_size = 10;
     const size_t prior_size = 3;
     vector<int> vec;

     // Fill it up with something
     for(size_t i = 0; i < prior_size; ++i) vec.push_back(static_cast<int>(i));

     // Iterate over appended elements
     vector<int>::iterator i = vec.begin();
     while(i != vec.end())
     {
      cout<<*i<<","<<vec.size()<<endl;
      if(vec.size()<arbit_size) AppendToVec(vec,i);
      ++i;
     }

     return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

0,3
1,4
2,5
1,6
1,7
1,8
1,9
1,10
1,10
1,10
Run Code Online (Sandbox Code Playgroud)

  • @All:请在downvoting之前阅读答案! (3认同)
  • 我不确定迭代器`i`在附加内容后会保持有效. (2认同)
  • 传递`i`的重点是使用相对信息来**更新**它在新的向量中. (2认同)

Col*_*nee 0

您需要随机访问该向量吗?如果不是,则 anstd::list更合适。我个人认为,在迭代向量时附加到向量并不是一个好主意。

  • `std::list` 是您不想使用的容器。由于其性能特征,它确实是最后的手段容器,并且仅在适当时对 O(1) `splice` 方法有用。 (3认同)