【问题标题】:Why Can't I move an Element of a map?为什么我不能移动地图的元素?
【发布时间】:2015-02-13 13:45:19
【问题描述】:

我希望能够更改 map 元素的键。

我认为处理这个问题的一个好方法是 move 来自 map 的元素,如下所示:

map<char, int> foo{{'a', 1}, {'b', 2}, {'c', 3}};

foo['z'] = move(*foo.find('c')).second;

for(auto& i: foo){
    cout << i.first << ' ' << i.second << endl;
}

这个输出:

1
b 2
c 3
z 3

而不是我希望的:

1
b 2
z 3

有什么办法可以做到吗?

【问题讨论】:

    标签: c++ dictionary key constants move


    【解决方案1】:

    首先,move 不会移动任何东西;它只是将其参数转换为 rvalue,以便其他东西可以从中移动。其次,从一个对象移动并不会破坏它,或者将它从容器中移除,它只是让它处于一个有效的、未指定的状态。最后,“移动”像pair&lt;const char, int&gt; 这样的简单类型只需复制它(尤其是const 意味着您无论如何都无法修改密钥,如果您强制更改它会破坏地图)。

    所以单独移动什么都不做,你的代码相当于

    foo['z'] = foo.find('c')->second;
    

    它只是添加了一个具有相同映射值副本的新元素。

    您可以将映射的值移动到新元素,然后删除旧元素。

    auto found = foo.find('c');
    if (found != foo.end()) {
        foo['z'] = move(found->second);
        foo.erase(found);
    }
    

    【讨论】:

      【解决方案2】:

      我希望能够更改地图元素的键。

      你不能。 mapvalue_typestd::pair&lt;const Key, Value&gt;const 部分很重要。该结构的整个内部布局是基于确保inserts 位于正确的位置。如果您可以更改密钥,则可以使整个结构无效。

      你正在运行的代码:

      foo['z'] = move(*foo.find('c')).second;
      

      只需插入一对 ('z', foo['c']) - move 不会做任何事情。请记住:move 只是对右值引用的强制转换——除非它实际上来自 moved,否则它不会做任何事情,因为我们正在处理基本类型,所以这里什么也没做,也不会产生任何影响。上面这行代码相当于:

      foo['z'] = foo.find('c')->second;
      

      这可能解释了为什么您会看到只插入一个新的键/值对而不删除'c' 的行为。

      “更改”密钥的正确方法是先将其擦除,然后再插入:

      auto it = foo.find('c');
      if (it != foo.end()) {
          foo.insert(std::make_pair('z', it->second));
          foo.erase(it);
      }
      

      【讨论】:

        猜你喜欢
        • 2011-04-07
        • 1970-01-01
        • 1970-01-01
        • 2017-11-07
        • 1970-01-01
        • 2019-10-18
        • 1970-01-01
        • 2015-04-30
        • 1970-01-01
        相关资源
        最近更新 更多