c++ - 在迭代排序的 stl 容器时插入元素
问题描述
当我的代码在迭代时将元素插入 std::set 时,我发现了意外的结果。我需要对此有所启发。
这是测试代码:
template<class Ti, class T>
void iteration_insertion(Ti start, Ti end, T& S){
for (auto ite=start;ite!=end;++ite){
auto before=*ite;
if(*ite % 2)
S.insert(*ite*2);
else
S.insert(*ite/2);
if(before!=*ite)
cout<<before<<","<<*ite<<endl;
}
}
void test() {
set<int> S1({4,7,10,13}),S2(S1);
cout<<"ascending\n";
iteration_insertion(S1.begin(),S1.end(),S1);
cout<<"descending\n";
iteration_insertion(S2.rbegin(),S2.rend(),S2);
}
结果:
ascending
descending
13,26
我们可以看到迭代器指向的元素在插入后有时会发生变化。但我不知道什么时候会发生。在测试代码中它只发生了一次,降序为 13。为什么在升序迭代中没有这种不匹配?为什么在降序迭代中 7 没有不匹配?如何防止它发生?我很好,新的附加值可以在以后迭代,这是意料之中的。我只是不希望通过插入更改迭代器。
测试代码可以是一种通用的启发式实践:从每个当前状态生成新状态以供进一步检查。
解决方案
为了考虑容器的所有元素,反向迭代器将元素的迭代器存储在取消引用时获得的元素之后。例如,结果rbegin()
内部存储了一个过去的迭代器。当您取消引用时,将生成存储的迭代器的副本,并且该副本在取消引用之前递减。
本质上,使用的标准代码的简化版本:
template<typename Iter>
struct reverse_iterator {
Iter base;
auto& operator++() { --base; return *this; }
auto& operator*() {
auto copy = base;
--copy;
return *copy;
}
};
auto std::set::rbegin() {
return reverse_iterator{this->end()};
}
将此应用于您的情况,您从rbegin()
. 取消引用它会为您提供最后一个元素 13。当您插入 26 时,它会在 13 之后插入,但在内部存储在ite
. 当您ite
再次取消引用时,会生成一个内部单过去迭代器的副本,并将其递减到 13 和 26 之间的位置,然后取消引用以提供 26。
这是解释的图片版本,以防有帮助:
推荐阅读
- python - How to interact with a python file's objects methods (putting inputs, alterting data, and getting outputs ) from the command line?
- post - Google Sheets to Salesforce with OAuth2 - Question about post mapping
- c# - VS告诉我“名称'xxx'在当前上下文中不存在”无论容器数据类型如何,即使我刚刚初始化它
- r - 粘贴和折叠矢量并用引号括起来
- python - 如何使用 Selenium 和 Python 将 AppleID 发送到登录字段
- spring-boot - Log4J2 的 Spring Boot 查找不起作用
- python - curl TRACE 的 Python 等效项
- docker - Gitlab 管道无法从 Dockerfile 构建映像,找不到 package.json
- javascript - 如何使用 jsPDF 创建项目符号列表
- c# - 实体框架单向导航