将元素从地图移动到另一个地图的更好方法

时间:2016-02-22 00:58:45

标签: c++ c++11

我必须为这个问题找到一个有效的解决方案。我有两张地图。我必须将一些元素从map1移动到map2(即从map1擦除并放入map2)。 我有钥匙通过它找到map1中的元素,即我现在正在做的事情:

bool temp;
temp = map1[key1];
map2[key1]=temp;
map1.erase(key1)

我为每个键(循环中)执行此操作

我的问题是我的解决方案是否更便宜 (我使用C ++ 11编译器)

5 个答案:

答案 0 :(得分:1)

std :: map文档:http://www.cplusplus.com/reference/map/map/

for (auto key : keys) // keys of elements to move
{
    try {
        map2[key] = std::move(map1.at(key)); // here is the C++ 11 optimization you looked for
        map1.erase(key);
    }

    // handle error if map1 does not store any element with current key
    catch (std::out_of_range & ex) {
        // TODO handle error
    }
}

答案 1 :(得分:1)

理想的解决方案只有在C ++ 17中才有可能: map::extract()

Std :: map通常实现为二叉树, 一棵二叉树为每个内存对象存储一个键值条目。 在这种假设下,可以通过简单地交换该内存的所有权来移动条目。 只需翻转相关的指针(包括重新平衡两棵树)即可完成此操作,如果最终结果要同时更改两棵树,则必须进行更新。

这不仅避免了在内存中移动对象,而且避免了任何内存分配和释放(具有不可预测的最坏情况性能)。

在C ++ 17之前,您必须实现自己的映射才能被允许这样做。

示例:

// Before Darwin, it was thought that whales were fish.
std::map<int, std::string> fish{{1,"whaleshark"}, {2,"whale"}, {3,"shark"}};
std::map<int, std::string> mammalia{{1,"cat"}, {2,"dog"}};

// Oops, the whale belongs to mammalia.
auto whale = fish.extract(2);
whale.key() = 3;
mammalia.insert(std::move(whale));

答案 2 :(得分:0)

你的临时变量是没有意义的;只写:

map2[key1] = map1[key1];
map1.erase(key1);

...虽然您的编译器已经可能为您做出“优化”。

关于价值本身,bool已经变得像原子一样 - 没有任何神奇的技巧可以让你更快地复制它。

可以(只要肯定已经存在map1[key1])就是要消除其中一个地图查找和零初始化:

auto it = map1.find(key1);
assert(it != map1.end());

map2.insert(std::make_pair(key1, it->second));
map1.erase(it);

但看看这是多么富有表现力!除非你确实遇到性能问题,否则不要这样做。

答案 3 :(得分:0)

如果value_type有默认构造函数,那么在名为std::swap的STL中,您不需要C ++ 11移动语义,这是一件好事。

std::swap(map1[key], map2[key]);
map1.erase(key1);

在您的情况下,我认为它只是复制bool值。但是,如果你的程序速度变慢,那么复制key_type我恐怕似乎无法使用这两个地图而不在它们之间移动条目,因为key_type总是const合格所以不能移动。

答案 4 :(得分:0)

通过迭代器插入整个地图,然后清除原始地图。

map2.insert(map1.begin(), map1.end());
map1.clear();