【问题标题】:Why this is an infinite loop为什么这是一个无限循环
【发布时间】:2018-01-13 08:15:20
【问题描述】:

我在下面使用 stl 声明了一个地图,并在其中插入了一些值。

#include<bits/stdc++.h>
int main()
{


map<int,int> m;
m[1]=1;
m[2]=1;
m[3]=1;
m[4]=1;
m[5]=1;
m[6]=1;

for(auto it=m.begin();it!=m.end();)
{
  cout<<it->first<<" "<<it->second<<endl;
  it=it++;
}

return 0;
}

当我执行上面编写的代码时,它最终陷入了无限循环。有人能告诉我为什么会这样吗? 我正在递增迭代器的值,然后将其存储在其中,下次执行循环时应​​该递增,最终它应该正常终止。我错了吗?

【问题讨论】:

标签: c++11


【解决方案1】:

坏行是it = it++;。这是未定义的行为!因为它没有被定义,所以当它增加时,在你的情况下,它在再次分配给它自己之前增加,它在增加之前的值被再次分配给它,所以它保持在第一个位置。 正确的行应该是it = ++it; 或只有++it;/it++;,因为它会自行改变。

编辑

这仅在内置类型中未定义,但在这里由 stl 中地图的源代码定义。

【讨论】:

  • it = ++it; 不应被推荐为正确的行。是的,从技术上讲它是正确的,但它与读者交流的只是“写这篇文章的人可能不明白 ++ 做了什么”。
【解决方案2】:

如果您尝试对 int 执行类似操作,您将收到警告:

int nums[] = { 1, 2, 3, 4, 5 };
for (int i = 0; i < sizeof nums / sizeof *nums; ) {
    cout << nums[i] << '\n';
    i = i++;
}

warning: operation on 'i' may be undefined [-Wsequence-point]

但是,当您使用具有运算符重载的类 (std::map::iterator) 时,编译器可能不够聪明,无法检测到这一点。

换句话说,您所做的是违反序列点,因此行为是未定义的行为。

【讨论】:

  • 序列点违规行为未定义,不是实现定义的。而且我认为 C++ 切换到了不涉及序列点的不同定义。
  • @melpomene 已修复
【解决方案3】:

后增量操作的行为如下:

iterator operator ++ (int) {
    auto copy = *this;
    ++*this;
    return copy;
}

因此,您的增量步骤发生的情况是迭代器 it 将被其原始值的副本覆盖。如果map 不为空,您的循环将停留在第一个元素上。

【讨论】:

    猜你喜欢
    • 2021-08-16
    • 2013-04-19
    • 2013-07-25
    • 2020-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多