将 const auto & 转换为迭代器
Converting const auto & to iterator
我最近阅读的许多帖子声称 for(const auto &it : vec)
与使用更长的迭代器语法 for(std::vector<Type*>::const_iterator it = vec.begin(); it != vec.end(); it++)
相同。但是,我发现 this post 说它们不一样。
目前,我正在尝试在 for 循环中删除一个元素,在它被使用之后,想知道是否有任何方法可以将 const auto &it : nodes
转换为 std::vector<txml::XMLElement*>::iterator
?
有问题的代码:
std::vector<txml2::XMLElement *> nodes;
//...
for (const auto &it : nodes)
{
//...
nodes.erase(it);
}
我很确定我可以将 std::vector<txml2::XMLElement*>
重写为 const 指针,但我不想这样做,因为这段代码目前仅用于调试。
您不应尝试将基于范围的 for 循环中的范围声明转换为迭代器,然后在迭代时将其删除。即使在迭代时调整迭代器也是危险的,你应该依赖算法。
你应该使用 Erase-remove idom.
您可以将它与 remove_if 一起使用。
它看起来像:
nodes.erase( std::remove_if(nodes.begin(), nodes.end(), [](auto it){
//decide if the element should be deleted
return true || false;
}), nodes.end() );
目前在技术规范中,是erase_if。
这是上面显示的相同行为的更简洁版本:
std::erase_if(nodes,[](auto it){
//decide if the element should be deleted
return true || false;
});
您得到的不是迭代器,而是对元素的引用。除非你想用它做一个 std::find
,否则很难从中得到一个迭代器。
向量很好,所以您可以为每个元素增加一个计数器并执行 nodes.begin() + counter
以获得迭代器,但它会打败重点。
同时在for循环中擦除迭代器会导致你在vector结束后进行迭代,你可以测试这段代码:
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v = {0,1,2,3,4,5,6};
for (int x : v) {
cout << x << endl;
if (x == 2) {
v.erase(v.begin() + 2);
}
}
return 0;
}
如果你想使用迭代器,只需用它们做一个循环,如果你还想删除一个中间循环,你必须遵循 this answer:
for (auto it = res.begin() ; it != res.end(); ) {
const auto &value = *it;
if (condition) {
it = res.erase(it);
} else {
++it;
}
}
请注意,您不需要指定迭代器的整个类型,auto
也可以。
我最近阅读的许多帖子声称 for(const auto &it : vec)
与使用更长的迭代器语法 for(std::vector<Type*>::const_iterator it = vec.begin(); it != vec.end(); it++)
相同。但是,我发现 this post 说它们不一样。
目前,我正在尝试在 for 循环中删除一个元素,在它被使用之后,想知道是否有任何方法可以将 const auto &it : nodes
转换为 std::vector<txml::XMLElement*>::iterator
?
有问题的代码:
std::vector<txml2::XMLElement *> nodes;
//...
for (const auto &it : nodes)
{
//...
nodes.erase(it);
}
我很确定我可以将 std::vector<txml2::XMLElement*>
重写为 const 指针,但我不想这样做,因为这段代码目前仅用于调试。
您不应尝试将基于范围的 for 循环中的范围声明转换为迭代器,然后在迭代时将其删除。即使在迭代时调整迭代器也是危险的,你应该依赖算法。
你应该使用 Erase-remove idom.
您可以将它与 remove_if 一起使用。
它看起来像:
nodes.erase( std::remove_if(nodes.begin(), nodes.end(), [](auto it){
//decide if the element should be deleted
return true || false;
}), nodes.end() );
目前在技术规范中,是erase_if。
这是上面显示的相同行为的更简洁版本:
std::erase_if(nodes,[](auto it){
//decide if the element should be deleted
return true || false;
});
您得到的不是迭代器,而是对元素的引用。除非你想用它做一个 std::find
,否则很难从中得到一个迭代器。
向量很好,所以您可以为每个元素增加一个计数器并执行 nodes.begin() + counter
以获得迭代器,但它会打败重点。
同时在for循环中擦除迭代器会导致你在vector结束后进行迭代,你可以测试这段代码:
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v = {0,1,2,3,4,5,6};
for (int x : v) {
cout << x << endl;
if (x == 2) {
v.erase(v.begin() + 2);
}
}
return 0;
}
如果你想使用迭代器,只需用它们做一个循环,如果你还想删除一个中间循环,你必须遵循 this answer:
for (auto it = res.begin() ; it != res.end(); ) {
const auto &value = *it;
if (condition) {
it = res.erase(it);
} else {
++it;
}
}
请注意,您不需要指定迭代器的整个类型,auto
也可以。