繁体   English   中英

迭代器-C ++ 11中没有匹配的擦除功能

[英]iterator - no matching erase function in c++11

我无法举例说明这种行为:

for (vector<File>::const_iterator it = this->files.begin(); it != this->files.end(); ++it) {
    if (...) erase(it); // break after, no need of ++it in else branch
}

其中File是我自己的类(不包括std),而this-> files是Files的向量

当我编译代码时(请参阅第2行

Path.cpp: In member function ‘void Path::rmFile(File&)’:
Path.cpp:190:24: error: no matching function for call to ‘std::vector<File>::erase(std::vector<File>::const_iterator&)’
Path.cpp:190:24: note: candidates are:
In file included from /usr/include/c++/4.7/vector:70:0,
             from Path.h:5,
             from Path.cpp:1:
/usr/include/c++/4.7/bits/vector.tcc:135:5: note: std::vector<_Tp, _Alloc>::iterator     std::vector<_Tp, _Alloc>::erase(std::vector<_Tp, _Alloc>::iterator) [with _Tp = File; _Alloc =     std::allocator<File>; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<File*,     std::vector<File> >; typename std::_Vector_base<_Tp, _Alloc>::pointer = File*]
/usr/include/c++/4.7/bits/vector.tcc:135:5: note:   no known conversion for argument 1     from ‘std::vector<File>::const_iterator {aka __gnu_cxx::__normal_iterator<const File*,     std::vector<File> >}’ to ‘std::vector<File>::iterator {aka __gnu_cxx::__normal_iterator<File*,     std::vector<File> >}’
/usr/include/c++/4.7/bits/vector.tcc:147:5: note: std::vector<_Tp, _Alloc>::iterator     std::vector<_Tp, _Alloc>::erase(std::vector<_Tp, _Alloc>::iterator, std::vector<_Tp,     _Alloc>::iterator) [with _Tp = File; _Alloc = std::allocator<File>; std::vector<_Tp,     _Alloc>::iterator = __gnu_cxx::__normal_iterator<File*, std::vector<File> >; typename     std::_Vector_base<_Tp, _Alloc>::pointer = File*]
/usr/include/c++/4.7/bits/vector.tcc:147:5: note:   candidate expects 2 arguments, 1 provided
make: *** [Path.o] Error 1

甚至文档都说可以,但是没有错误匹配函数来调用std :: vector :: erase(std :: vector :: const_iterator&)确实很奇怪。

我真的需要能够通过迭代器删除矢量项。 有人可以帮我吗? 提前解冻。

这里有三个错误。

for (vector<File>::const_iterator it = this->files.begin(); it != this->files.end(); ++it) {
    if (...) erase(it); // break after, no need of ++it in else branch
}

第一个错误是您错误地将代码剪切并粘贴到StackOverflow中。 你要粘贴的是

for (vector<File>::const_iterator it = this->files.begin(); it != this->files.end(); ++it) {
    if (...) this->files.erase(it); // break after, no need of ++it in else branch
}

第二个错误是编译器警告您的:无法通过const_iterator修改集合。 (编辑: 好吧,显然C ++ 11添加了这样一种方法,但是libstdc ++并不立即支持它。 )这就是const_部分的意思! 如果要修改集合,请使用普通的旧iterator

for (vector<File>::iterator it = this->files.begin(); it != this->files.end(); ++it) {
    if (...) this->files.erase(it); // LOOK OUT, THERE'S STILL A BUG
}

第三个错误是,一旦您对集合调用std::vector::erase ,该集合中的所有迭代器(和const_iterator )都将变得不可用 对此的标准术语是: erase 使迭代器无效 (这样做的原因是std::vector行为基本上就像一个大的堆分配缓冲区,并且允许在vector上调用resize等效于在缓冲区上执行realloc (1) ,并且允许调用erase来调用resize (因为如果erase向量中的一半元素,则可能期望堆分配相应地缩小)。

因此,使用这种幼稚的for循环方法将无法正常工作 您需要做的是使用标准算法remove_if

#include <algorithm>

auto predicate = [](const File& f) { return f.ShouldBeErasedOrWhatever(); }
auto newEndIterator = std::remove_if(this->files.begin(), this->files.end(), predicate);
this->files.erase(newEndIterator, this->files.end());  // erase everything after "newEndIterator"

f.ShouldBeErasedOrWhatever()替换为原始代码中的“ ... ”。 现在,您拥有有效的,惯用的C ++ 11,可以正确地完成工作-没有错误!


(1) –关于“等价于realloc ”的注释:当然,它并不是真正的 realloc 这实际上是一个类型安全的过程,可以根据需要调用move构造函数和析构函数。 vector知道它不是一般安全memcpy在C ++中的任意对象。

假设您的示例代码不正确,并且实际上是files.erase(it) ,那么const_iterator版本仅在C ++ 11中添加,因为您没有使用auto ,所以看起来好像没有。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM