下面的 C++ 代码似乎可以工作,我很想知道如何工作:
std::map<char,char> mymap;
mymap['a'] = 'A'; mymap['b'] = 'B'; mymap['c'] = 'C';
mymap['d'] = 'D'; mymap['e'] = 'E'; mymap['f'] = 'F';
mymap['g'] = 'G'; mymap['h'] = 'H'; mymap['i'] = 'I';
bool erase = true;
for (auto& [key, value] : mymap) {
if (erase) mymap.erase(key); // Erasing every other item!!
erase = !erase;
}
Run Code Online (Sandbox Code Playgroud)
我在迭代地图时修改地图。来自 JVM 世界,我期待着某种CuncurrentModificationException......但它似乎在 C++ 中工作得很好。
难道这真的坏了,我只是运气好?如果不是,那么它在幕后是如何工作的?
大多数这样做的例子都使用迭代器,我猜这是有原因的吗?for (auto& it = mymap::begin(); it != mymap::end; ) { it++ }这种方式对我来说看起来更干净,我怀疑有人会在没有充分理由的情况下选择更冗长和不太清晰的方法。
C++std使用窄契约来允许程序更快。
狭义合同是指并非每项操作都有保证结果的合同。如果您违反了合同条款,C++ 不对您的程序的行为提供任何保证。
在这种情况下,您可以在使用引用该元素的迭代器进行迭代时销毁该元素。这会使迭代器无效,并且循环++中的隐式高级操作for(;)违反了您与std库之间的约定。
有了一份广泛的合同,你会在这里得到类似的例外。如果合约较弱,你会得到未定义的行为。有时它“有效”,有时它崩溃,有时它会将您的浏览器历史记录通过电子邮件发送给您的祖母并删除您的 Gmail 帐户。
都是对违反合同行为的有效回应。C++ 标准对可执行文件的功能没有限制。这可能包括时间旅行(不,这不是一个笑话;UB 允许编译器在程序到达 UB 之前更改它在行上所做的事情)。
我亲自写了一个remove_erase_if算法来解决这个问题一次。是的,它使用迭代器。
| 归档时间: |
|
| 查看次数: |
809 次 |
| 最近记录: |