【问题标题】:Is it possible to remove elements from a vector of shared_ptr?是否可以从 shared_ptr 的向量中删除元素?
【发布时间】:2019-04-26 22:26:19
【问题描述】:

说我有

vector<shared_ptr<string>> enemy;

如何从敌人向量中移除元素?

提前感谢您的帮助

**编辑(上下文中的代码)

void RemoveEnemy( vector<shared_ptr<Enemy>> & chart, string id )
{
  int i = 0;
  bool found = FALSE;
  for(auto it = chart.begin(); it != chart.end(); i++)
  {
    if(id == chart[i]->GetEnemyID() )
    {
        found = TRUE;
        chart.erase(it);
    }
}

上面的代码让我出错

【问题讨论】:

标签: c++ vector shared-ptr


【解决方案1】:

您删除元素的方式与从任何std::vector 中删除任何元素的方式相同——例如,通过std::vector::erase() 方法。您只需要一个iterator 即可删除所需的元素。

在您的情况下,由于您存储的是 std::shared_ptr&lt;std::string&gt; 对象而不是存储实际的 std::string 对象,因此您可能需要使用类似 std::find_if() 的方法来查找包含所需字符串值的向量元素,例如:

void removeEnemy(string name)
{
    auto iter = std::find_if(enemy.begin(), enemy.end(),
        [&](auto &s){ return (*s == name); }
    );
    if (iter != enemy.end())
        enemy.erase(iter);
}

更新:在您添加的新代码中,您错误地将索引和迭代器混合在一起。如果vector 不为空,您将创建一个无限循环,因为您永远不会增加控制循环的it 迭代器,而是增加您的索引i 变量(看看会发生什么当您不给变量提供唯一且有意义的名称时?)。因此,您最终会超出vector 的范围,进入周围的内存。这就是您收到段错误错误的原因。

即使您(尝试)使用迭代器来循环遍历vector,您也使用索引来访问元素,而不是取消引用迭代器来访问元素。在这种情况下,您根本不需要使用索引,仅使用迭代器就足够了。

试试这个:

void RemoveEnemy( vector<shared_ptr<Enemy>> & chart, string id )
{
  for(auto it = chart.begin(); it != chart.end(); ++it)
  {
    if (id == it->GetEnemyID() )
    {
      chart.erase(it);
      return;
    }
}

或者,使用我之前建议的那种代码:

void RemoveEnemy( vector<shared_ptr<Enemy>> & chart, string id )
{
    auto iter = std::find_if(chart.begin(), chart.end(),
        [&](auto &enemy){ return (enemy->GetEnemyID() == id); }
    );
    if (iter != chart.end())
        chart.erase(iter);
}

【讨论】:

  • 每当我尝试这个时,我都会收到这个错误:错误:没有匹配函数调用'std::vector<:shared_ptr> >::erase(int&)'
  • @dcjboi 我展示的代码不会产生那个错误。 vector::erase()vector::iterator 作为输入,在vector 上调用std::find_if() 返回vector::iterator,而vector::iterator 未实现为int&amp;。您是否尝试将 index 传递给 erase() 而不是 iterator?请编辑您的问题以显示您正在使用的实际代码。
  • @dcjboi 您正在将索引与迭代器混合。没有理由这样做。
  • 我应该删除我的索引吗?
【解决方案2】:

您的代码的问题是erase() 使迭代器无效。您必须使用it = chart.erase(it)

【讨论】:

    【解决方案3】:

    我喜欢我的,它可以高速移除外星人,而无需关心其他物品的排序。有偏见的删除!

    注意:remove_if 最常与erase 一起使用,它将保留其余元素的顺序。但是,partition 不关心元素的顺序,而且速度更快。

    partition-test.cpp:
    make partition-test &amp;&amp; echo 1 alien 9 alien 2 8 alien 4 7 alien 5 3 | ./partition-test

    #include <algorithm>
    #include <iostream>
    #include <iterator>
    #include <memory>
    #include <string>
    #include <vector>
    
    using namespace std;
    
    template <typename T>
    ostream &operator<<(ostream &os, const vector<T> &container) {
      bool comma = false;
      for (const auto &x : container) {
        if (comma)
          os << ", ";
        os << *x;
        comma = true;
      }
      return os;
    }
    
    int main() {
      vector<shared_ptr<string>> iv;
      auto x = make_shared<string>();
      while (cin >> *x) {
        iv.push_back(x);
        x = make_shared<string>();
      }
      cout << iv << '\n';
    
      iv.erase(partition(begin(iv), end(iv),
                         [](const auto &x) { return *x != "alien"s; }),
               end(iv));
      cout << iv << '\n';
      return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 2021-11-13
      • 2010-10-02
      • 2017-11-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多