为什么我无法移动地图的元素?

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

本文关键字:元素 地图 移动 为什么      更新时间:2023-10-16

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

我认为处理这个问题的一个好方法是movemap中的元素,如下所示:

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

有没有办法让我做到这一点?

首先,move不移动任何东西;它只是将其参数转换为右值,这样其他东西就可以从中移动。其次,从对象中移动不会破坏它,也不会将它从容器中删除,它只是使它处于有效的、未指定的状态。最后,"移动"像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);
}

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

你不能。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;

这可能解释了为什么您看到的行为只是插入一个新的密钥/值对,而CCD_。

"更改"密钥的正确方法是擦除密钥,然后插入:

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