gpt4 book ai didi

c++ - 迭代器 - 在 C++11 中没有匹配的删除函数

转载 作者:行者123 更新时间:2023-11-30 00:51:56 25 4
gpt4 key购买 nike

我无法解释这种行为:

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 的 vector

当我编译我得到的代码时(参见第 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说没问题,但是错误 no matching function for call to std::vector::erase(std::vector::const_iterator&) 真的很奇怪。

我真的需要能够通过迭代器删除 vector 项。有人可以帮我吗?提前致谢。

最佳答案

这里有三个错误。

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
}

第二个 bug 是编译器警告您的:无法通过 const_iterator 修改集合。 (编辑:Okay, apparently C++11 added such a way, but libstdc++ didn't support it immediately.)这就是 const_ 部分的意思!如果要修改集合,请使用普通的旧迭代器:

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 vector 中一半的元素,您可能期望堆分配相应地缩小。)

因此,使用这种天真的 for 循环方法,您尝试做的将行不通。您需要做的是使用标准算法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 ;它确实是一个类型安全的过程,可以根据需要调用移动构造函数和析构函数。 vector 知道在 C++ 中 memcpy 任意对象通常不安全。

关于c++ - 迭代器 - 在 C++11 中没有匹配的删除函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20306307/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com