Clause 22 不要直接修改set或multiset中的键值

Clause 22 不要直接修改set或multiset中的键值
如果修改了set中的键值(即作为排序用的主键的值),就会破坏set容器的有序性。
看如下程序:
#include < iostream >
#include
< set >
using   namespace  std;
class  Test
{
public :
    
int  key;
    Test(
int  k):key(k)
    {
    }
    
void  setkey( int  newKey)
    {
        key
= newKey;
    }
    
bool   operator < ( const  Test  &  t)  const
    {
        
return  key < t.key;
    }
};
int  main()
{
    
set < Test > ts;
    
for ( int  i = 1 ;i < 10 ;i ++ )
    {
        Test t(
10 - i);
        ts.insert(t);
    }
    
set < Test > ::iterator it;
    
for (it = ts.begin();it != ts.end();it ++ )
        
if (it -> key == 5 )
        {
                it
-> key = 20 ;
            
break ;
        }
    
for (it = ts.begin();it != ts.end();it ++ )
        cout
<< it -> key << endl;
}

上述程序中,把键值为5的元素的键值修改成了20. 最后输出结果为1 2 3 4 20 6 7 8 9.即set容器的有序性被破坏了。

另外,看下面的程序
 1  #include < iostream >
 2  #include < vector >
 3  #include < string >
 4  #include < cmath >
 5  #include < set >
 6  using   namespace  std;
 7  class  Test
 8  {
 9  public :
10       int  key;
11      Test( int  k):key(k)
12      {
13      }
14       void  setkey( int  newKey)
15      {
16          key = newKey;
17      }
18       bool   operator < ( const  Test  &  t)  const
19      {
20           return  key < t.key;
21      }
22  };
23  int  main()
24  {
25       set < Test > ts;
26       for ( int  i = 1 ;i < 10 ;i ++ )
27      {
28          Test t( 10 - i);
29          ts.insert(t);
30      }
31       set < Test > ::iterator it;
32       for (it = ts.begin();it != ts.end();it ++ )
33           if (it -> key == 5 )
34          {
35              ((Test)(*it)).setkey(20);
36               break ;
37          }
38      cout << it -> key << endl;
39  }
在第35行中,先把*it强制转换成了Test类型,然后改变了key的值。但是在第38行的输出中,结果不是20,而是5.这时因为 这种类型转换的结果是一个临时的匿名对象,他是*it的一个拷贝,setkey操作被作用到了这个临时变量上。
解决这个问题,可以把地35句换成 const_cast<Test&>(*it).setkey(20); 或者static_cast<Test&>(*it).setkey(20); 这样输出结果就是20.

注意,const_cast与static_cast的区别。
他们都用于强制类型转换。但是const_cast只能作用于引用或者指针,而static_cast即可作用于引用或者指针,还可作用于对象。所以,const_cast<Test>(*it).setkey(20); 这条语句编译时会出错。而static_cast<Test&>(*it).setkey(20); 可以通过编译,但如果把这句话放在上面程序的第35句,输出的结果仍是5,而不是20.

你可能感兴趣的:(Clause 22 不要直接修改set或multiset中的键值)