如何告诉std :: set'刷新'它的排序?

时间:2009-06-20 09:57:09

标签: c++ stl

如果集合中元素的值发生更改,则排序可能不再正确。正如这个小程序所示:

#include <algorithm>
#include <iostream>
#include <set>
#include <string>

struct Comp
{
    bool operator()(const std::string * lhs, const std::string * rhs)
    {
        return *lhs < *rhs;
    }
};

int main()
{
    typedef std::set<std::string*, Comp> MySet;
    MySet mySet;

    std::string * a = new std::string("a");
    mySet.insert(a);

    std::string * c = new std::string("c");
    mySet.insert(c);

    std::string * b = new std::string("b");
    mySet.insert(b);

    for (MySet::iterator it = mySet.begin(); it != mySet.end(); ++it)
    {
        std::cout << *(*it) << std::endl;
    }

    // Ouput has correct order:
    // a
    // b
    // c


    *b = "z";
    std::cout << std::endl;

    std::string * d = new std::string("d");
    mySet.insert(d);    

    for (MySet::iterator it = mySet.begin(); it != mySet.end(); ++it)
    {
        std::cout << *(*it) << std::endl;
    }

    // Output no longer ordered correctly:
    // a
    // d
    // z
    // c

    return 0;
}

如何判断设备“刷新”其内部排序?

5 个答案:

答案 0 :(得分:9)

这里非常相似的主题(虽然不是很重复,因为你通过自定义比较存储指向可变对象的指针):

what happens when you modify an element of an std::set?

基本上,不要做你想做的事。相反,当您想要修改set持有指针的对象时,首先删除指针,然后修改对象,然后重新插入指针。

答案 1 :(得分:5)

简单地说,你不能。如果将项目放入集合中,则不应以更改其顺序的方式更改项目。如果需要以这种方式更改项目,则需要将其从set(set :: erase)中删除,然后使用新值重新插入新项目(std :: insert)。

答案 2 :(得分:2)

  

如果集合中元素的值发生变化

停止!这不合法。

std::set没有提供任何方法来做你所要求的事情,因为它已经是一个先决条件,永远不需要手动重新订购。

答案 3 :(得分:1)

值得指出的是,如果您使用vs 2008,std::set实现支持非const迭代器,使您描述的代码使用该库成功编译。在其他stl实现中(例如sgi's),set::const_iteratorset::iterator属于同一类型,会抱怨显式设置新的键值。

答案 4 :(得分:0)

使用不同的比较谓词将其复制到自身。

std::set MySet();

/* add entries*/

MySet = std::set(MySet.begin(), MySet.end(), Comp);

通常这用于指定不同的比较操作,例如使用存储的类/结构的不同部分对其进行排序。