为什么我不能移动地图的元素?

时间:2015-02-13 13:45:20

标签: c++ dictionary key const move

我希望能够更改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;
}

输出:

  

a 1
  b 2
  c 3
  z 3

而不是我的希望:

  

a 1
  b 2
  z 3

我有办法实现这个目标吗?

2 个答案:

答案 0 :(得分:4)

首先,move不会移动任何东西;它只是将其参数转换为 rvalue ,以便其他东西可以从中移动。其次,从一个物体移动不会破坏它,或者从容器中移除它,它只是使它处于一个有效的,未指定的状态。最后,&#34;移动&#34;像pair<const char, int>这样的简单类型只需要复制它(特别是const表示无论如何都无法修改键,如果你强制改变它就会破坏地图。)

所以移动本身什么也没做,你的代码等同于

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

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

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

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

答案 1 :(得分:3)

  

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

你不能。 value_type的{​​{1}}为mapstd::pair<const Key, Value>部分非常重要。结构的整个内部布局取决于确保const在正确的位置。如果您可以更改密钥,则可能会使整个结构无效。

您正在运行的代码:

insert

只需插入foo['z'] = move(*foo.find('c')).second; 对 - ('z', foo['c'])不做任何事情。请记住:move只是对左右参考的强制转换 - 它除了实际上move之外没有做任何事情,这里什么也没做,也不会做无论如何,因为我们正在处理基本类型。上面的代码行相当于:

move

这可以解释为什么您在没有foo['z'] = foo.find('c')->second; 被删除的情况下只看到插入新键/值对的行为。

正确的方式改变&#34;一个关键是擦除它然后插入它:

'c'