Effective_STL 学习笔记(二十二) 避免原地修改 set 和 multiset 的健

 

正如所有标准关联容器,set 和 multiset 保持它们的元素有序,容器的正确行为依赖于它们保持有序,如果改变一个元素的值,新值不在正确的位置,将破坏容器的有序性。

 

对于 map 和 multimap 容器,改变容器里一个键值的程序不能编译,

map<K, V> 或 multimap<K, V> 类型的对象中的元素类型是 pair<const K, V>,

键的类型是 const K 不能改变。  

 

而对于 set 和 multiset 为 set<T> 和 multiset<T>,非 const 的原因:

想要元素 T 中,非元素的键的部分可以被修改

1. 如果不关心移植性,想要改变 set 或 multiset 中元素的值,只要确定不要改变元素的键的部分

2. 如果在乎移植性,就认为 set 和 mutiset 中的元素不能被修改,至少不能在没有映射的情况下。

映射掉引用:

1   if( i != se.end() )
2   {
3     const_cast<Employee &> (*i).setTitle("Corporate Deity"); //映射掉 *i 的常量性
4   }

告诉编译器把映射的结果当作一个(非常数)Employee 的引用,然后在引用上调用setTitle

 

如果总可以工作而且总是安全的改变 set、multiset、map 或 multimap 里的元素,通常按五个步骤去做:

1. 定位你想要改变的容器元素

2. 拷贝一份要修改的元素

3. 修改副本

4. 从容器里删除元素,通常通过调用 erase

5. 把新值插入容器

以安全可移植的方式写:

 1   EmpIDSet se;
 2   Employee selectedID;
 3   . . .
 4   EmpIDSet::iterator i = se.find( selectedID );  // 第一步:找到要改变的元素
 5   if( *i != se.end() )
 6   {
 7     Employee e(*i);   // 第二步:拷贝这个元素
 8     se.erase( i++ );  // 第三步:删除这个元素,自增这个迭代器以保持它有效
 9     e.setTitle( "Corporate Deity" );  // 第四步:修改这个副本
10     se.insert(i, e);             // 第五步:插入新值,位置和原来位置一样
11   }

 

总的来说,避免原地修改 set 和 multiset 的键

 

posted @ 2018-11-27 19:47  KidyCharon  阅读(157)  评论(0编辑  收藏  举报