迭代向量,删除某些项目,因为我去(iterate vector, remove certain it

2019-08-31 08:32发布

我有一个std :: vector的m_vPaths; 我去,我会遍历这个向量和调用::的DeleteFile(strPath的)。 如果我成功地删除文件,我会从向量中删除。 我的问题是我可以绕过不必使用两个向量? 是否有可能更适合于什么,我需要做不同的数据结构?

例如:使用迭代器几乎我想要做什么,但问题是,一旦你删除使用迭代器,所有迭代器失效。

 std::vector<std::string> iter = m_vPaths.begin();
    for( ; iter != m_vPaths.end(); iter++) {
        std::string strPath = *iter;
        if(::DeleteFile(strPath.c_str())) {
            m_vPaths.erase(iter);   
                //Now my interators are invalid because I used erase,
                //but I want to continue deleteing the files remaining in my vector.    
        }
    }

我可以用两个向量和我将不再有问题,但有没有这样做我想要做的更好的,更有效的方法?

顺便说一句,柜面目前还不清楚,m_vPaths声明如下(在我的班级):

std::vector<std::string> m_vPaths;

Answer 1:

检查出std::remove_if

#include <algorithm> // for remove_if
#include <functional> // for unary_function

struct delete_file : public std::unary_function<const std::string&, bool> 
{
    bool operator()(const std::string& strPath) const
    {
        return ::DeleteFile(strPath.c_str());
    }
}

m_vPaths.erase(std::remove_if(m_vPaths.begin(), m_vPaths.end(), delete_file()),
                m_vPaths.end());

使用std::list停止无效的迭代器的问题,虽然你失去了随机访问。 (和缓存性能,在一般情况)


根据记录,你会实现你的代码的方法是:

typedef std::vector<std::string> string_vector;
typedef std::vector<std::string>::iterator string_vector_iterator;

string_vector_iterator iter = m_vPaths.begin();
while (iter != m_vPaths.end())
{
    if(::DeleteFile(iter->c_str()))
    {
        // erase returns the new iterator
        iter = m_vPaths.erase(iter);
    }
    else
    {
        ++iter;
    }
}

但是,你应该使用std::remove_if (重新发明轮子是坏的)。



Answer 2:

erase()方法返回一个新的(有效的)迭代器指向删除的一个之后的下一元素。 你可以使用这个迭代继续进行循环:

std::vector<std::string>::iterator iter;
for (iter = m_vPaths.begin(); iter != m_vPaths.end(); ) {
    if (::DeleteFile(iter->c_str()))
        iter = m_vPaths.erase(iter);
    else
        ++iter;
}


Answer 3:

由于删除一个文件的时候,它可能并不重要,但我还是劝通过向后矢量迭代 - 这样你通常是从(接近)删除项目的矢量结束。 删除的项目所花费的时间正比于在矢量下列它的项数。 如果(举例来说)你有100文件名的载体,你成功地删除所有的人,你会100次复制的最后一个元素的过程中(与第二复制到最后一个元素99次,依此类推)。

OTOH,如果从月底开始和向后工作,你不要复制,只要删除文件是成功的。 您可以使用反向迭代器向后遍历向量不改变太多别的。 例如,使用的remove_if GMAN的代码应该撕裂()继续工作(仅稍快一点)只是代rbegin()为()开始,并结束。

另一种可能性是使用双端队列,而不是一个向量-一个deque可以抹掉年底集合在固定时间内开始项目。



文章来源: iterate vector, remove certain items as I go