我有一个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;
检查出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
(重新发明轮子是坏的)。
在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;
}
由于删除一个文件的时候,它可能并不重要,但我还是劝通过向后矢量迭代 - 这样你通常是从(接近)删除项目的矢量结束。 删除的项目所花费的时间正比于在矢量下列它的项数。 如果(举例来说)你有100文件名的载体,你成功地删除所有的人,你会100次复制的最后一个元素的过程中(与第二复制到最后一个元素99次,依此类推)。
OTOH,如果从月底开始和向后工作,你不要复制,只要删除文件是成功的。 您可以使用反向迭代器向后遍历向量不改变太多别的。 例如,使用的remove_if GMAN的代码应该撕裂()继续工作(仅稍快一点)只是代rbegin()为()开始,并结束。
另一种可能性是使用双端队列,而不是一个向量-一个deque可以抹掉年底或集合在固定时间内开始项目。