条款22:避免原地修改set和multiset的键

来源:互联网 发布:mysql 日志文件 编辑:程序博客网 时间:2024/04/30 16:25

因为set或multiset里的值不是const,所以试图改变它们可以编译。本条款的目的是提醒你如果你改变set或multiset里的元素, 你必须确保不改变一个键部分——影响容器有序性的元素部分。如果你做了,你会破坏容器,再使用那个容器将产生未定义的结果, 而且那是你的错误。另一方面,这个限制只应用于被包含对象的键部分。对被包含元素的所有其他部分来说,是开放的:随便改变!

即使set和multiset的元素不是const,实现仍然有很多方式可以阻止它们被修改。例如,实现可以让用于set<T>::iterator的operator*返回一个常数T&。即,它可以让set的迭代器解引用的结果是set元素的常量引用。在这样的实现下,将没有办法修改set或multiset的元素,因为所有访问那些元素的方法都将在让你访问之前加一个const。

这样的实现合法吗?可以证明是。也可以证明不是。标准在这里有矛盾,而根据Murphy定律(译注:Murphy定律就是“If there are two or more ways to do something, and one of those ways can result in a catastrophe, then someone will do it.”(当有两条或更多的路让你抉择,如果其中一条会导致失败,那么你一定会选到它。)随着时间流逝,这一“定律”逐渐进入习语范畴,其内涵被赋予无穷的创意,也出现了众多的变体,其中最著名的一条也被称为Finagle定律,具体内容为:“If anything can go wrong, it will.”(如果一个东西可能会出错,那它一定会出错。)这一定律被认为是对“Murphy定律”最好的模仿和阐述。),不同实现会以不同的方式解释它们。结果是发现这些代码,我早先声明可以编译的,却经常在某些STL实现上不能编译: 如果不关心移植性,你想要改变set或multiset中元素的值,而且你的STL实现让你侥幸成功,继续做。只是要确定不要改变元素的键部分,即,会影响容器有序性的元素部分。如果你在乎移植性,就认为set和multiset中的元素不能被修改,至少不能在没有映射的情况下。