当修改 std::set 的元素时会发生什么?
例如,如果我通过迭代器更改 std::set 的元素,我知道它不是“重新插入”或“重新排序”,但是否有提及它是否会触发未定义的行为? 例如,我想象插入会搞砸。 有没有提到具体发生了什么?
If I change an element of an std::set, for example, through an iterator, I know it is not "reinserted" or "resorted", but is there any mention of if it triggers undefined behavior? For example, I would imagine insertions would screw up. Is there any mention of specifically what happens?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您不应直接编辑存储在集中的值。 我从MSDN文档中复制了这个,有点权威:
为什么这是很容易理解的。
set
实现将无法知道您已经修改了其背后的值。 正常的实现是红黑树。 更改值后,该实例在树中的位置将是错误的。 您可能会看到各种错误行为,例如exists
查询由于搜索到了树的错误分支而返回错误结果。You should not edit the values stored in the set directly. I copied this from MSDN documentation which is somewhat authoritative:
Why this is is pretty easy to understand. The
set
implementation will have no way of knowing you have modified the value behind its back. The normal implementation is a red-black tree. Having changed the value, the position in the tree for that instance will be wrong. You would expect to see all manner of wrong behaviour, such asexists
queries returning the wrong result on account of the search going down the wrong branch of the tree.确切的答案取决于平台,但作为一般规则,“密钥”(您放入集合中的内容或地图的第一种类型)应该是“不可变的”。 简单来说就是不应该修改,也不存在自动重新插入的情况。
更准确地说,用于比较键的成员变量不得修改。
Windows vc编译器相当灵活(用VC8测试),这段代码编译:
输出是100 25 40,这显然没有排序...糟糕...
不过,当您想要修改不参与运算符的数据时,这种行为还是很有用的。。 但你最好知道自己在做什么:这就是你因过于灵活而付出的代价。
有些人可能更喜欢 gcc 行为(使用 3.4.4 进行测试),这会给出错误“分配只读位置”。 您可以使用 const_cast 来解决它:
现在也在 gcc 上编译,相同的输出:100 25 40。
但至少,这样做可能会让您想知道发生了什么,然后转到堆栈溢出并查看此线程:-)
The precise answer is platform dependant but as a general rule, a "key" (the stuff you put in a set or the first type of a map) is suppose to be "immutable". To put it simply, that should not be modified, and there is no such thing as automatic re-insertion.
More precisely, the member variables used for to compare the key must not be modified.
Windows vc compiler is quite flexible (tested with VC8) and this code compile:
The output is 100 25 40, which is obviously not sorted... Bad...
Still, such behavior is useful when you want to modify data not participating in the operator <. But you better know what you're doing: that's the price you get for being too flexible.
Some might prefer gcc behavior (tested with 3.4.4) which gives the error "assignment of read-only location". You can work around it with a const_cast:
That's now compiling on gcc as well, same output: 100 25 40.
But at least, doing so will probably makes you wonder what's happening, then go to stack overflow and see this thread :-)
你不可以做这个; 它们是const。
set
没有任何方法可以检测到您对内部元素进行的更改,因此您无法这样做。 相反,您必须删除并重新插入该元素。 如果您使用复制成本高昂的元素,则可能必须改用指针和自定义比较器(或改用支持右值引用的 C++1x 编译器,这将使事情变得更好)。You cannot do this; they are
const
. There exists no method by which theset
can detect you making a change to the internal element, and as a result you cannot do so. Instead, you have to remove and reinsert the element. If you are using elements that are expensive to copy, you may have to switch to using pointers and custom comparators (or switch to a C++1x compiler that supports rvalue references, which would make things a whole lot nicer).