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

来源:互联网 发布:java log4j%意思 编辑:程序博客网 时间:2024/05/21 05:18

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_, intgrade_)

              : name(name_)

              , grade(grade_)

       {}

 

       bool operator<(student const&rhs) const

       {

              returnname < rhs.name;

       }

 

       bool operator==(student const&rhs) const

       {

              returnname == 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>::iteratori = 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>

 

usingstd::map;

usingstd::string;

 

structstudent_periphery {

    intgrade;

};

 

map<string,student_periphery> students;

 

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

可能原因:

set returns const iterators (the standardsays set::iterator is const, and that set::const_iterator and set::iterator mayin fact be the same type - see 23.2.4/6 in n3000.pdf) because it is an orderedcontainer. If it returned a regular iterator, you'd be allowed to change theitems 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

 

原创粉丝点击