移动std::map对象与移动std::map所有元素是否完全等价?
两种std::map移动操作的核心差异
二者完全不等效,核心差异可以从以下几个维度区分:
1. 时间复杂度天差地别
- case1:
std::map的移动赋值是O(1)复杂度,仅交换容器内部的根节点指针、元素计数、分配器等元数据,完全不会触碰存储的元素,不管map里有多少个元素,操作都可以瞬间完成。移动后原mp处于合法但未指定的状态,通常表现为空。 - case2:迭代器范围移动插入是O(n log n)复杂度,需要遍历原
mp的所有节点,逐个移动构造元素到新容器,每插入一个元素都要执行红黑树的查找、平衡逻辑,元素量越大性能开销越高。
2. 对元素类型的要求不同
- case1:移动map本身不需要调用任何元素的构造/析构函数,和
Obj的类型特性完全无关,哪怕Obj没有移动构造、甚至不可拷贝都可以正常执行。 - case2:要求
Obj至少支持移动构造,如果Obj的移动构造不是noexcept甚至没有移动构造,这个操作会自动退化为元素的拷贝构造。
3. 原map的状态不同
- case1操作完成后,原
mp的所有节点都已经被转移到mp2,原mp本身是空的,可以直接复用。 - case2操作完成后,原
mp的节点结构完全保留,大小和操作前一致,只是每个节点里存储的Obj对象处于被移动后的合法但未指定状态,直接访问这些Obj的成员属于未定义行为,必须重新赋值后才能正常使用原mp的元素。
额外提示:你给出的case2代码存在语法错误,漏掉了末尾的右括号,正确写法是
std::move(std::begin(mp), std::end(mp), std::inserter(mp3, std::end(mp3)));
内容的提问来源于stack exchange,提问作者Yves。
相关产品推荐
相关产品推荐

