【问题标题】:C++ Regarding pointer/reference with remove_ifC++ 关于使用 remove_if 的指针/引用
【发布时间】:2012-01-18 15:08:54
【问题描述】:

我正在尝试使用 remove_if 删除向量中的元素以进行过滤。问题是当我编译编码时,没有错误,但是当我尝试使用过滤器功能时,弹出错误说我无法取消引用迭代器。我不知道哪里出了问题,希望你们能帮助发现问题。 这是我的部分代码

bool filter_C (Teacher &t) 
{ 
return (t.getCat() != compare); //compare is a static string
}
void filterTeacherCategory(vector<Teacher> &t)
{
    vector<Teacher>::iterator i;
    Teacher *ptr;
    i = remove_if(t.begin(), t.end(), filter_C);
    ptr = &(*i);
    for (i = t.begin(); i != t.end(); ++i)
    {
        ptr->getName();
        cout << "\t";
        ptr->getGender();
        cout << "\t";
        ptr->getPhone();
        cout << "\t";
        ptr->getCategory();
        cout << "\t\t";
        ptr->getLocation();
        cout << "\n";
     }
}

【问题讨论】:

    标签: c++ pointers reference dereference remove-if


    【解决方案1】:

    要真正擦除元素,您需要执行类似的操作

    t.erase(std::remove_if(...),t.end());
    

    remove_if 只为您提供一个删除了元素的范围(新端)。在您的代码中,您的 ptr 正是新的结束(即,超过最后一个有效元素)。

    【讨论】:

      【解决方案2】:

      remove_if 返回向量的新端。所以你应该像这样迭代

      vector<Teacher>::iterator i;
      vector<Teacher>::iterator newenditer = remove_if(..);
      
      
      for (i = t.begin(); i != newenditer ; ++i)
      {
             Teacher& tchr= *i;
             cout << tchr.getName() << "\n";
             cout << tchr.getPhone() << "\n";
      
      }
      

      来自 remove_if 文档

      将 pred 应用于范围 [first,last) 中的元素,并从结果范围中删除不返回 false 的元素。结果范围由 first 和函数返回的迭代器之间的元素组成,该迭代器指向范围的新端。

      保留未删除元素的相对顺序,而超出新范围的元素仍然有效,尽管具有未指定的值。

      一般来说,在 remove_if 之后擦除剩余元素是个好主意

      vector<Teacher>::iterator i;
      vector<Teacher>::iterator newenditer = remove_if(..);
      t.erase( newenditer , t.end() );
      

      现在 t.begin() 和 t.end() 之间的所有内容都是有效且良好的,所以你可以这样做

       for (i = t.begin(); i != t.end() ; ++i)
          {
          }
      

      【讨论】:

      • 这行得通,但现在我有另一个问题。反正有没有把remove_if变成像remove_ifnot这样的东西?我知道这听起来有点好笑……
      • @NewUserSeekingHelp:是的,您可以用“否定符”包装您的谓词 (filter_C):remove_if(t.begin(), t.end(), not1(filter_C))std::not1 需要 #include &lt;functional&gt;
      • 只需创建一个新的 filter_D 即为 t.getCat() != compare 并调用 remove_if
      • 哦..没想到..谢谢!但是现在我的问题是第二次激活过滤器功能时,向量中的最后一个元素会出现两次..知道为什么吗?
      • @NewUserSeekingHelp: remove_if 实际上不会从向量中删除元素(因为它只能访问迭代器,而不是向量本身)。相反,它将它们移动到最后,并告诉你新的结束。有关如何从向量中删除不需要的元素,请参阅 Michael Krelin 的回答。
      【解决方案3】:

      这一行

      ptr = &(*i);
      

      在序列的过滤部分结束后取消引用元素。如果您的过滤器根本不匹配任何元素,因此没有删除任何内容,那么您正在尝试将迭代器取消引用到向量末尾之后的一个,这将给出您报告的错误。即使不是i 指向的元素的内容也不太可能有很大帮助。

      完全不清楚你想要ptr 是什么,但我很确定不是这个。

      【讨论】:

      • 我认为你说得对;仅当没有“删除”任何内容时,上面的代码才是错误的,否则将指针指向第一个 removed 元素是完全有效的(尽管可能是不好的习惯)。但是,如果没有删除任何内容,正如您正确指出的那样,那将需要取消引用 one-past-last 元素,这当然是无效的。
      • 因为过滤选项是系统给出的,是从向量中的对象中获取的
      猜你喜欢
      • 1970-01-01
      • 2012-11-04
      • 2019-10-15
      • 1970-01-01
      • 1970-01-01
      • 2019-06-11
      • 1970-01-01
      • 1970-01-01
      • 2017-11-03
      相关资源
      最近更新 更多