在std :: vector中使用函数erase

时间:2017-11-14 06:42:49

标签: c++ pointers vector erase

我有这个功能,其目的是删除类BaseFile的指针 来自一个叫做儿童的载体

 //children is vector of type vector<BaseFile*>
void Directory::removeFile(BaseFile* file)
{
   for(int i = 0 ; (unsigned)i < children.size() ; i++)
    {
        if ((children[i]->getName()).compare(file->getName()) == 0)
        {    
            BaseFile* a = children[i];
            children.erase(children.begin()+i);
            if(a != nullptr) 
            {
                delete a;//err in this line : double free or corruption
            }
        } 
    }
}

第一个问题是为什么我在行中出错(删除a;)? 剂量方法擦除删除指针删除它? 如果是,我怎么能从矢量中删除指针而不删除它在堆/堆栈中的内容?

1 个答案:

答案 0 :(得分:2)

您需要做的是使用std::remove_if来获取没有匹配元素的向量。

但是,一旦您对std::remove_if进行了调用,您就无法将delete匹配的项目视为documentation州(强调我的):

  

通过移动(通过移动分配)范围内的元素来完成移除,使得不被移除的元素出现在范围的开头。保留的元素的相对顺序被保留,容器的物理大小不变。 指向新逻辑结束和范围物理结束之间的元素的迭代器仍然是可解除引用的,但元素本身具有未指定的值(根据MoveAssignable后置条件)

因此我们将直接在谓词中处理删除。请注意,我们还必须注意不要将任何内容加倍,以便我们通过使用std::unordered_set

跟踪已删除的项目
void Directory::removeFile(BaseFile *file) {
     std::unordered_set<BaseFile*> deleted_set { file }; // Just to avoid deleting the input argument if it's stored in children as well...
     auto match_it = std::remove_if(begin(children), end(children),
          [&](BaseFile *current_file) -> bool {
              bool result = current_file->getName().compare(file->getName()) == 0;
              if (result && end(deleted_set) == deleted_set.find(current_file)) {
                  delete current_file;
                  deleted_set.insert(current_file);
              }
              return result;
          });
     children.erase(match_it, end(children));
}

最后,我希望您作为file参数提供的指针不是children的成员,如果是,那么您不会结束{{ 1}} - ing it!

注意:您的案例中是否可以使用智能指针?似乎delete对象对Directory中存储的BaseFile个对象拥有所有权...所以也许children会有所帮助......