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

Why Can't I move an Element of a map?

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

有什么方法可以实现吗?

I want to be able to change the key of an element of a map.

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

您的代码 运行:

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

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

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

这或许可以解释为什么您会看到仅插入一个新的 key/value 对而没有 'c' 被删除的行为。

"change"密钥的正确方法是擦除它然后插入它:

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

首先,move不移动任何东西;它只是将其参数转换为 rvalue,以便其他东西可以从它移动。其次,从一个对象中移出并不会破坏它,或者将它从容器中移除,它只是让它处于有效的、未指定的状态。最后,"moving" 像 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);
}