Как сказать std :: set для «обновления» своего порядка? - PullRequest
4 голосов
/ 20 июня 2009

Если значение элемента в наборе изменяется, порядок может быть неправильным. Как показано в этой маленькой программе:

#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 ]

9 голосов
/ 20 июня 2009

Здесь очень похожая тема (хотя и не совсем дубликат, потому что вы храните указатели на изменяемые объекты с пользовательским сравнением):

что происходит при изменении элемента std :: set?

По сути, не делай того, что пытаешься сделать. Вместо этого, когда вы хотите изменить объект, на который set содержит указатель, сначала удалите указатель, затем измените объект, а затем снова вставьте указатель.

5 голосов
/ 20 июня 2009

Просто вы не можете. Если вы помещаете элемент в набор, вы не должны изменять элемент таким образом, чтобы изменить его порядок. Если вам нужно изменить элемент таким способом, вам нужно удалить его из набора (set :: erase) и заново вставить новый элемент (std :: insert) с новым значением.

2 голосов
/ 18 октября 2013

Если значение элемента в наборе изменяется

Стоп! Это не может происходить на законных основаниях.

std::set не предоставляет никаких средств для выполнения того, что вы просите, потому что это уже является обязательным условием, что повторный заказ вручную никогда не потребуется.

1 голос
/ 21 июня 2009

Стоит отметить, что если вы используете vs 2008, реализация std::set поддерживает неконстантные итераторы, благодаря чему код, который вы описываете, успешно компилируется с использованием этой библиотеки. В других реализациях stl (например, sgi's ), set::const_iterator и set::iterator относятся к одному и тому же типу, который жаловался бы на явную установку нового значения ключа.

0 голосов
/ 21 июня 2009

Скопируйте его в себя, используя другой предикат сравнения.

std::set MySet();

/* add entries*/

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

Обычно это используется для указания другой операции сравнения, например, для сортировки с использованием другой части сохраненного класса / структуры.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...