[英]iterator - no matching erase function in c++11
I can't exmplain this behaviour: 我无法举例说明这种行为:
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
}
where File is my own class (std not included) and this->files is vector of Files 其中File是我自己的类(不包括std),而this-> files是Files的向量
when I compile the code I get (see line 2 ) 当我编译代码时(请参阅第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
even the doc says it's ok, but error no matching function for call to std::vector::erase(std::vector::const_iterator&) is really wierd. 甚至文档都说可以,但是没有错误匹配函数来调用std :: vector :: erase(std :: vector :: const_iterator&)确实很奇怪。
I really need to be able to delete vector item by iterator. 我真的需要能够通过迭代器删除矢量项。 Can anybody help me please?
有人可以帮我吗? Thaks in advance.
提前解冻。
You have three bugs here. 这里有三个错误。
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
}
The first bug is that you incorrectly cut-and-pasted your code into StackOverflow. 第一个错误是您错误地将代码剪切并粘贴到StackOverflow中。 What you meant to paste was
你要粘贴的是
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
}
The second bug is what the compiler is warning you about: there's no way to modify a collection through a const_iterator
. 第二个错误是编译器警告您的:无法通过
const_iterator
修改集合。 (EDIT: Okay, apparently C++11 added such a way, but libstdc++ didn't support it immediately. ) That's what the const_
part means! (编辑: 好吧,显然C ++ 11添加了这样一种方法,但是libstdc ++并不立即支持它。 )这就是
const_
部分的意思! If you want to modify the collection, use a plain old iterator
: 如果要修改集合,请使用普通的旧
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
}
The third bug is that once you call std::vector::erase
on a collection, all iterators (and const_iterator
s) into that collection become unusable . 第三个错误是,一旦您对集合调用
std::vector::erase
,该集合中的所有迭代器(和const_iterator
)都将变得不可用 。 The Standard terminology for this is that erase
invalidates iterators . 对此的标准术语是:
erase
使迭代器无效 。 (The reason for this is that std::vector
behaves basically like a big heap-allocated buffer, and calling resize
on the vector is allowed to do the equivalent of realloc
(1) on the buffer, and calling erase
is allowed to call resize
(because if you erase
half the elements in the vector, you're probably expecting the heap-allocation to shrink accordingly).) (这样做的原因是
std::vector
行为基本上就像一个大的堆分配缓冲区,并且允许在vector上调用resize
等效于在缓冲区上执行realloc
(1) ,并且允许调用erase
来调用resize
(因为如果erase
向量中的一半元素,则可能期望堆分配相应地缩小)。
So, what you're trying to do won't work using that naive for-loop approach. 因此,使用这种幼稚的for循环方法将无法正常工作 。 What you need to do is use a standard algorithm , namely
remove_if
: 您需要做的是使用标准算法 , 即
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"
Replace f.ShouldBeErasedOrWhatever()
with whatever your " ...
" is in the original code. 将
f.ShouldBeErasedOrWhatever()
替换为原始代码中的“ ...
”。 Now you have valid, idiomatic C++11 that does the right thing — with no bugs! 现在,您拥有有效的,惯用的C ++ 11,可以正确地完成工作-没有错误!
(1) – Note on "the equivalent of realloc
": Of course it's not really realloc
; (1) –关于“等价于
realloc
”的注释:当然,它并不是真正的 realloc
; it's really a type-safe process that calls move-constructors and destructors as needed. 这实际上是一个类型安全的过程,可以根据需要调用move构造函数和析构函数。
vector
knows it's not generally safe to memcpy
arbitrary objects in C++. vector
知道它不是一般安全memcpy
在C ++中的任意对象。
假设您的示例代码不正确,并且实际上是files.erase(it)
,那么const_iterator
版本仅在C ++ 11中添加,因为您没有使用auto
,所以看起来好像没有。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.