更改for循环的第三部分后,不展开for循环的结果 [英] unexpend for-loop result after change the third part of for-loop

查看:71
本文介绍了更改for循环的第三部分后,不展开for循环的结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我在源文件中使用 for-loop 时,得到未消耗的结果.这是最小的源文件(我隐藏了文件头和 print_set 的功能):

When I use for-loop in my source file, I get a unexpend result. Here is the minimum source file (I hide the head of file and the function of print_set):

// the main function
int main(void) {
    set<int> test{3, 5};
    print_set(test);

    for (auto it = test.begin(); it != test.end();) {
        auto node = test.extract(it);
        ++it;
    }
    print_set(test);
}

然后我使用命令来编译并运行:

Then I use command to compile and run:

$ g++ --version
g++ (Dedian 8.3.0-6) 8.3.0
... (not very important infomation for this question)
$ g++ -std=c++17 temp.cpp
$ ./a.out
[ 3 5 ]
[ ]

现在一切正常,但是在将 for-loop 部分更改为该部分之后(我将 ++ it 替换为 for-loop的第三部分的头):

Now all thing goes well but after I change the for-loop part to this (I replace ++it to the third part of for-loop's head):

    for (auto it = test.begin(); it != test.end(); ++it) {
        auto node = test.extract(it);
    }

现在的结果是:

$ ./a.out
[ 3 5 ]
zsh: segmentation fault (core dumped) ./a.out

Zsh 是我正在使用的Linux shell,它不是很重要的信息.在查看了有关 for循环的某些网页后,例如等,我仍然不知道为什么?是虫子吗?为什么这些不相等并且有两个不同的结果?因为方法 extract ?但是为什么第一部分可以运行?

Zsh is the Linux shell that I am using that is not very important infomation. After view some web pages about for-loop like this, etc., I still do not know why? Is it a bug? Why these are not equal and have two different results? Because the method extract? But why can the first part can run?

谢谢.

推荐答案

来自 std :: set< T> :: extract()文档:

提取节点会使迭代器对提取的元素无效.

Extracting a node invalidates the iterators to the extracted element.

在调用 test.extract(it)之后,迭代器 it 不再有效.即使递增它或将其与另一个迭代器进行比较,也未定义操作.提取后对 it 唯一安全的操作是:

After the call to test.extract(it), the iterator it is no longer valid. Even incrementing it or comparing it to another iterator are not defined operations. The only safe things you can do to it after extraction are:

  • 让它被破坏.
  • 为其分配一个有效的迭代器.

其他任何事情都会导致未定义的行为,因此问题中的两个代码示例均会调用未定义的行为.问一个为什么做与另一个不同的事情是没有意义的问题.每次运行程序时,它们可能各自执行不同的操作-包括您希望代码执行的操作!

Anything else causes undefined behavior, therefore both code examples in your question invoke undefined behavior. Asking why one does something different than the other is a meaningless question. They might each do something different each time the program is run -- including what you wanted the code to do!

无法解释未定义的行为,并且这样做总是浪费时间.

要修复代码,您需要复制迭代器,增加原始副本,然后提取副本.这正是后增量运算符的作用:

To fix the code, you would need to copy the iterator, increment the original, then extract the copy. This is exactly what the post-increment operator does:

for (auto it = test.begin(); it != test.end();) {
    auto node = test.extract(it++);
}

在此示例中,在提取之前将 it 进行了突变.此示例具有明确定义的行为,并将一个一组地提取每个元素.

In this example, it is mutated before extraction happens. This example has well-defined behavior, and will extract each element in the set one by one.

这篇关于更改for循环的第三部分后,不展开for循环的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆