[英]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.