通过迭代器更改集合中的元素

aLu*_*aLu 0 c++ compiler-errors set

我想更改集合(QSet)中的元素:

for(PSet::iterator pIt = P.begin(); pIt != P.end(); ++pIt)
  pIt->xp = 0;
Run Code Online (Sandbox Code Playgroud)

编译器不会让我这样做(“C3892:'var':你不能分配给 const 变量”)。集合迭代器似乎总是恒定的,因为担心更改元素可能会破坏其在集合中的正确位置。

就我而言,PSet 是一组结构,我为其定义了自己的哈希函数:

struct P
{
  P(int id, const Data_t& data)
     :xp(_INFINITY_)
     ,id(id)
     ,data(data){}

  int xp;  
  const int id;
  const Data_t data;
};
Run Code Online (Sandbox Code Playgroud)

我的哈希函数不考虑非常量成员 xp,因此我的上述分配对于集合中元素的顺序应该是完全安全的。我不想删除该元素并重新插入它,因为性能实际上是这里的一个问题。

我想我可以使用 const 强制转换,但这会损害我的代码的可读性并且看起来像一个令人讨厌的黑客。我还有其他选择吗?

qua*_*dev 5

QSet不允许修改 元素,因为它可能通过修改哈希结果之一来破坏容器的内部结构。

\n\n

至于标准关联容器,这在标准部分 \xc2\xa7 23.2.4

\n\n
\n

关联容器的迭代器属于双向迭代器类别。对于值类型与键类型相同的关联容器,iterator 和 const_iterator 都是常量迭代器。未指定 iterator 和 const_iterator 是否为同一类型。

\n
\n\n

如果您知道您的修改对已排序的位置元素没有影响,则使用 aconst_cast是可以的罕见情况之一。

\n\n

然而,惯用的方法是使用提示插入

\n\n
    \n
  1. 找到要修改的元素
  2. \n
  3. 制作元素的副本
  4. \n
  5. 修改副本
  6. \n
  7. 删除元素
  8. \n
  9. 插入副本,使用可用的提示插入(a 没有QSet
  10. \n
\n\n

例子:

\n\n
  s.erase(original);\n  // modify p ...\n  s.insert(copy, hint);\n
Run Code Online (Sandbox Code Playgroud)\n\n

注意事项:

\n\n
    \n
  1. 这同样适用于其他关联容器。
  2. \n
  3. Scott Meyers 的“ Effective STL,第 22 项”对此问题进行了广泛讨论。
  4. \n
  5. std::vector有时考虑作为替代品是个好主意std::set
  6. \n
\n