【问题标题】:What is the std::vector::iterator's index in the vector?向量中的 std::vector::iterator 索引是什么?
【发布时间】:2014-07-10 17:44:59
【问题描述】:

我有一个std::vector<Bullet> bullets,在下面的 for 循环中,如果它不再存在,我想从向量中删除一个子弹。

我的计划是删除带有pop_back() 的元素。如果向量中有多个元素,我想先将要删除的元素与向量中的最后一个元素交换,然后调用pop_back()

for (std::vector<Bullet>::iterator b = bullets.begin(); b != bullets.end(); ++b) {
  if(!b->isAlive()) {
    if (bullets.size() > 1) {
      std::iter_swap(bullets + ..., bullets.end());
    }
    bullets.pop_back();
  }
}

问题是iter_swap中的第一个参数。我查了http://www.cplusplus.com/reference/algorithm/iter_swap/,第一个参数的语法是向量+元素的位置。

如何找出向量中b 的索引?

【问题讨论】:

  • 要么我遗漏了一些东西,要么你需要一个 iterator 作为第一个元素并且已经有了正确的迭代器:b
  • @Cyber​​ 因为这需要线性时间,而交换和弹出需要恒定时间。
  • 为了记录,b - bullets.begin() 会给出索引。
  • @delnan 您的for 循环需要线性时间。删除-擦除交换和弹出。
  • 你不想iter_swap(b, bullets.end() - 1)(强调“- 1”)吗?

标签: c++ vector iterator swap


【解决方案1】:

如果控制一个元素是否被移除的条件是:

object->isAlive()

那么你应该使用STL的方式来进行删除,即erase-remove idiom:

bullets.erase(std::remove_if(bullets.begin(), bullets.end(), 
[](Bullet const& b) {
   return !b.isAlive(); 
}), bullets.end());

现在,要回答您的特定问题,可以像这样获得向量v 中的迭代器it 索引:

auto indx = std::distance(v.begin(), it); 

【讨论】:

    【解决方案2】:

    有一种更简单的方法可以过滤std::vector

    #include <algorithm>
    
    auto part = std::remove_if(
        bullets_.begin(),
        bullets_.end(),
        [](const Bullet &bullet) { return !bullet.isAlive(); });
    bullets_.erase(part, bullets_.end());
    

    这会将向量划分为活子弹和死子弹,然后删除带有死子弹的片段。

    std::remove_if() 函数类似于partition(),但只保留第一个分区的顺序。

    【讨论】:

    • 谢谢。那里的auto 是什么类型的?我的不支持。
    • @A.D.是时候升级你的编译器了……或者至少开启现代 C++ 支持。那是 C++11。
    • 是的,我知道。我想知道类型是什么,所以我可以用auto 交换它,然后使用你的解决方案。
    • @A.D.如果您不支持auto,您可能还需要将 lambda 替换为仿函数对象。您可以将 auto 替换为您的向量的迭代器类型。
    猜你喜欢
    • 1970-01-01
    • 2015-12-15
    • 2015-10-21
    • 1970-01-01
    • 2020-07-23
    • 1970-01-01
    • 1970-01-01
    • 2018-04-03
    • 2017-07-03
    相关资源
    最近更新 更多