If the value of an element in a set changes the ordering may be no longer correct. As illustrated in this little program:
#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;
}
How can I tell the set to 'refresh' its internal sorting?
Very similar subject here (though not quite a duplicate, because you're storing pointers to mutable objects with a custom comparison):
what happens when you modify an element of an std::set?
Basically, don't do what you're trying to do. Instead, when you want to modify an object that a set
holds a pointer to, remove the pointer first, then modify the object, then re-insert the pointer.
Simply, you can't. If you place an item into a set, you should not change the item in a way that changes its ordering. If you need to change an item in this way then you need to remove it from the set (set::erase), and reinsert a new item (std::insert) with the new value.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With