C ++为什么这些代码有效?

时间:2016-05-08 13:27:33

标签: c++ pointers stl

为什么可以打印' e'它被删除后?

set <int> s;
for (auto &e : s){
    s.erase(e);
    cout << e;
}

同样发生在这里,

list <int> l;
l.push_back(1);
l.push_back(2);
auto it = l.begin();

为什么会这样?

l.erase(it++);
cout << *it;

这不是吗?

l.erase(it);
it++;
cout << *it;

3 个答案:

答案 0 :(得分:4)

在这两种情况下,您都有未定义的行为。在第一个e中是对已被破坏的对象的引用(悬空引用)。对该引用的任何访问都是未定义的行为。它可能会崩溃,打印随机数或格式化您的硬盘。在这种情况下,打印出您最初想到的数字。

在列表的情况下,有效的案例表现如下:

auto it2 = it;
it++;
l.erase(it2);
cout << *it;

在第二种情况下,您可以:

l.erase(it);
// it is no longer valid at this point.  You cannot use it.
it++;  // Undefined behaviour.
cout << *it; // Anything can happen

答案 1 :(得分:2)

没有&#34;工作&#34;。

只有似乎可以正常工作

你的程序实际上有一个致命的错误。

编译器在一般情况下不会为您检测到此错误(因为它们无法解决),因此您的代码仍会编译。在一般情况下,C ++运行时不会为您检查内存边界(因为您不会为您不使用的内容付费,这将是一个昂贵的强迫我们使用功能)所以你的代码仍在运行。

但是你写了一个无效的程序。

答案 2 :(得分:0)

对于列表,当你传递参数时,迭代器在赋值给擦除函数后已经递增,因此迭代器仍然有效并指向集合中的下一个元素。

在第二种情况下,迭代器无效,因为它在增量之前已被擦除。