如果您在c++中更新一个集合的成员,该集合会自动更改顺序吗

in case you update a member of a set in c++, does the set automatically change the order?

本文关键字:集合 成员 顺序 如果 更新 c++ 一个      更新时间:2023-10-16

我想使用类型为node的集合S,我想操作集合中的成本部分,并按cost:对集合进行排序

struct node
{
int label;
long cost=LONG_MAX;
bool visited=false;
bool operator < (const node &other) const { return cost < other.cost; }
}
set<node> S;
//here i just want to update the cost of a node in my set S
set<node>::iterator it=S.find(vertex);
*it.cost=200;

这会自动改变布景的顺序吗?

这会自动更改集合中的顺序吗?

它不仅不会更改set的顺序,而且操作本身也是非法的。关联容器迭代器为键提供了const类型,因此示例中的*it具有node const类型。

仔细想想,这是确保容器提供不变量的唯一方法。毕竟,it->cost = 200怎么可能更新底层的set呢?也许如果C++有反射,迭代器去引用到某个重载了operator=的代理,那么。。。是的,听起来一团糟。

当前"更新"set中元素的惯用方法包括擦除、修改,然后重新插入

auto it = S.find(vertex);
node cur = std::move(*it);
auto next = S.erase(it);
cur.cost = 200;
S.insert(next, cur);

无可否认,这相当乏味。


有一项建议(P0083R2)将在未来对此进行改进。


C++17的更新:该提议已被接受。现在您想要使用extract():

auto node = S.extract(vertex);
node.value().cost = 200;
S.insert(std::move(node));

这将避免您类型的额外副本和额外的分配/解除分配。

通常不能更改集合的现有内容。这是一个肮脏的小秘密,但std::set迭代器实际上是const_iterators。继续编译它,你会得到编译错误。

当然,有一些方法可以解决这个问题,但它们会导致未定义的行为。