迭代器 - c ++ 11中没有匹配的擦除函数
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了迭代器 - 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
甚至doc说它没关系,但错误没有匹配函数调用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
修改集合。 (编辑:Okay, apparently C++11 added such a way, but libstdc++ didn't support it immediately.)这就是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
s)都会变得无法使用。标准术语是erase
使迭代器无效。 (原因是std::vector
的行为基本上像一个大的堆分配缓冲区,并且允许在向量上调用resize
在缓冲区上执行相当于realloc
(1)的操作,并且调用erase
可以调用resize
(因为如果你erase
向量中的一半元素,你可能期望堆分配相应地缩小)。)
所以,你正在尝试做的事情将无法使用那种天真的for-loop方法。你需要做的是使用标准算法,namely 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-constructors和析构函数。 vector
知道在C ++中memcpy
任意对象通常不安全。
假设您的示例代码不正确并且它确实是files.erase(it)
,那么const_iterator
版本仅在C ++ 11中添加,看起来您没有使用auto
。
以上是关于迭代器 - c ++ 11中没有匹配的擦除函数的主要内容,如果未能解决你的问题,请参考以下文章