STL set 容易引起误解的一个地方

STL set 容易引起误解的一个地方

#include <set>

#include <string>

#include <iostream>

 

using namespace std;

using std::set;

using std::string;

 

struct student {

       string name;

       int grade;

 

       student(string const& name_, int grade_)

              : name(name_)

              , grade(grade_)

       {}

 

       bool operator<(student const& rhs) const

       {

              return name < rhs.name;

       }

 

       bool operator==(student const& rhs) const

       {

              return name == rhs.name;

       }

};

 

int main(void)

{

       set<student> students;

       students.insert(student("Li Lei", 5));

       students.insert(student("Han Meimei", 5));

       students.insert(student("Jim Green", 5));

 

       for (set<student>::iterator i = students.begin();

              students.end() != i;

              ++i)

       {

              (i->grade)+=1;

       }

       return 0;

}

STL set是只读机制,set 的只读制度是非常龌龊的, 简而言之, 只要你敢往这个坑里面放, 你就得接受它们以后再也无法修改的命运

   student 类的 key  name,  grade 没有关系, 原则上来说, 修改后者并不会破坏 set 的存储结构. 然而, 编译器一棒子打死, 不许改, 除非剩下的成员全部 mutable 修饰.
    
只读制度悲剧的根源在于set 所谓的 key 撑死只是个假象value_type 这玩意儿就是 key_type 本身, 既然名份这个大框框定了, 那再怎么折腾也只是折腾, 二奶再怎么被临幸也是二奶, 总也到不了拿证那一步.
    
key 导致的不仅仅是不能改, 重要的是还不能查! 看看 set::find 函数的参数, 要的又是阴魂不散的 key_type. 这意味着什么? 意味着 Han MM 同学报出她名字的时候, 还查不出她几年级, 而必须要利用她的名字, 伪造一个充气娃娃放进去才能找到! 看到这里我就败了, 这明摆着就是不让我用 set, 让我转投 map ? 一个也许可行的方案是

#include <map>

#include <string>

 

using std::map;

using std::string;

 

struct student_periphery {

    int grade;

};

 

map<string, student_periphery> students;

 

Dev-Cpp g++下编译不通过, 但是在aix xlC下通过的代码

可能原因:

set returns const iterators (the standard says set::iterator is const, and that set::const_iterator and set::iterator may in fact be the same type - see 23.2.4/6 in n3000.pdf) because it is an ordered container. If it returned a regular iterator, you'd be allowed to change the items value out from under the container, potentially altering the ordering.没办法,如果想修改的话只能先删除再添加咯。这点stl做的有点傻阿。我改后面那个值与你索引的那个有嘛关系,为啥不可以修改捏?
只应该对索引的那个键进行const保护塞。。。

 

 

set一般是用红黑树来实现的,所以结点的值不能修改,因为改了之后会对树造成破坏(不再是排序二叉树),之后对set的任何操作 都可能得到不确定的结果。
如果要修改,你可以erase掉某个结点修改后再重新insert

 

标准的STL这里肯定是不能改的,所以你的程序会有严重的移植问题
由于set不是一个简单的线性结构,如果能够修改,就不能防止人为地修改键值,而这会造成set的崩溃。

 

 

在我的VS2008中这段代码也可以很好的运行,可能在VS2008中有这样的机制吧

 

 

Reference

http://www.taoyard.net.cn/?p=79

http://super-jiju.spaces.live.com/blog/cns!806C498DDEE76B61!787.entry

http://www.lslnet.com/linux/dosc1/26/linux-219500.htm

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值