【问题标题】:updating the value of a key in a std::map更新 std::map 中键的值
【发布时间】:2011-08-30 18:37:57
【问题描述】:

假设我们有一个简单的结构,如下所示

struct T{
  int x;
  int y;
};
T t1, t2;

还假设我有一个map<T, int> myMap,并且两个T 类型的结构仅使用它们的x 值进行比较。 IE。 t1 < t2 iff t1.x < t2.x。我正在尝试更新 myMap 上键的一些 y 值。这不应该影响地图如何看到键。除了删除旧元素并插入新元素之外,还有其他方法吗?

【问题讨论】:

  • 为什么键是T 而不是简单的int?您可能想解释一下xy 的含义以及为什么使用T 而不是int 作为键有意义
  • @David:没错。我的观点。因此,我的建议。:-)
  • 我只是简化了我的问题。作为我的地图键的原始对象具有更多的属性,并且在更多的上下文中使用,我无法仅根据作为地图键的条件来分离属性。

标签: c++ stl map


【解决方案1】:

如果您确定y 不参与您的类的“逻辑状态”并且仅仅是一个实现细节,那么您可以将其声明为mutable

struct T
{
  int x;
  mutable int y;
  bool operator<(const T& rhs) const { return x < rhs.x; }
};

现在你应该可以更改y

for (auto it = m.begin(); it != m.end(); ++it)
{
  it->first.y = -2; // ouch? But it won't invalidate the map's invariants.
}

【讨论】:

    【解决方案2】:

    不,map 不能让你修改键,因为这可能会使映射不变量(元素的顺序)无效——你知道它不会,但 map 不能知道,所以它在谨慎的一面,不允许这样做。

    删除并重新插入是一种正确的方法。将键视为不可变的。

    【讨论】:

      【解决方案3】:

      如果y不参与比较,你可以将其标记为mutable,这样即使值为常量也可以修改。

      【讨论】:

        【解决方案4】:

        std::map 的键是 const。所以你不能改变它。

        另外,如果你只使用x 来比较密钥,那你为什么要std::map&lt;T,int&gt;?为什么不这样:

        std::map<int, std::pair<T,int> > data; //where keys would be t.x
        

        毕竟,在您的地图中,键实际上是t.x

        【讨论】:

        • 但是,让y 成员mutable 怎么样?因为它“逻辑上”使对象保持不变?
        • @Kerrek SB,您是否应该将其发布为答案?
        【解决方案5】:

        您可以修改T::y,如果它不影响比较运算符的行为。另一方面,修改地图的键是不好的风格,它应该是不可变的。标准库的一些实现确实允许修改密钥。

        【讨论】:

        • “标准库的一些实现确实允许修改密钥。”这些实现被破坏了(或者,如果你愿意,不实现标准库。)你能说出它们的名字吗?
        【解决方案6】:

        映射中的键是常量,尝试将新值复制到新映射中。

        【讨论】:

          【解决方案7】:

          就像 Cat 说的那样,您不应该出于很多充分的理由更改密钥,但您似乎知道的足够多,可以继续前进。

          用 const_cast 去掉键的 constness,你就不能造成各种伤害.... err changes。只需仔细检查比较运算符在修改后是否仍然返回相同的结果。

          【讨论】:

          • 我本来想说这是个坏主意,但如果有选择地将mutable 设为struct 的非关键成员可能会在非map 情况下导致问题.两者都是坏主意,让我们面对现实吧,但根据上下文,一个可能比另一个差一些。 ;-)
          猜你喜欢
          • 1970-01-01
          • 2019-12-02
          • 1970-01-01
          • 2018-04-21
          • 2011-10-28
          • 1970-01-01
          • 2016-09-02
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多