我发现更新操作std::set很繁琐,因为cppreference上没有这样的API .所以我现在做的是这样的:
//find element in set by iterator
Element copy = *iterator;
... // update member value on copy, varies
Set.erase(iterator);
Set.insert(copy);
Run Code Online (Sandbox Code Playgroud)
基本上迭代器返回的Set是a const_iterator,你不能直接改变它的值.
有一个更好的方法吗?或者也许我应该std::set通过创建我自己的(我不知道它是如何工作的...)来覆盖.
Ter*_*fey 72
set返回const_iterators(标准说set<T>::iterator是const,这set<T>::const_iterator并set<T>::iterator可能实际上是相同类型的-见23.2.4/6在n3000.pdf),因为它是一个有序的容器.如果它返回常规iterator,则允许您从容器下面更改项值,可能会改变排序.
你的解决方案是改变一个项目的惯用方法set.
Mat*_* M. 24
在简单的情况下,有两种方法可以做到这一点:
mutable不属于键的变量Key Value对(并使用一个std::map)现在,问题是针对棘手的情况:当更新实际修改key对象的一部分时会发生什么?你的方法有效,但我承认它很乏味.
Bar*_*rry 10
在C++ 17中,你可以做得更好extract(),感谢P0083:
// remove element from the set, but without needing
// to copy it or deallocate it
auto node = Set.extract(iterator);
// make changes to the value in place
node.value() = 42;
// reinsert it into the set, but again without needing
// to copy or allocate
Set.insert(std::move(node));
Run Code Online (Sandbox Code Playgroud)
这将避免您的类型的额外副本和额外的分配/释放,并且还将适用于仅移动类型.
你也可以extract按键.如果密钥不存在,则返回空节点:
auto node = Set.extract(key);
if (node) // alternatively, !node.empty()
{
node.value() = 42;
Set.insert(std::move(node));
}
Run Code Online (Sandbox Code Playgroud)
更新:虽然以下情况属于现在,但该行为被视为缺陷,将在即将发布的标准版本中进行更改.多么难过
有几点使您的问题相当混乱.
std::set是一个类,因此不能返回任何东西.s.erase(iter),那就iter不是了const_iterator.erase需要一个非const迭代器.std::set返回迭代器的所有成员函数返回非const迭代器,只要该集合也是非const.只要更新不更改元素的顺序,就可以更改集合元素的值.以下代码编译并正常工作.
#include <set>
int main()
{
std::set<int> s;
s.insert(10);
s.insert(20);
std::set<int>::iterator iter = s.find(20);
// OK
*iter = 30;
// error, the following changes the order of elements
// *iter = 0;
}
Run Code Online (Sandbox Code Playgroud)
如果您的更新更改了元素的顺序,则必须擦除并重新插入.