【问题标题】:Move a std::map vs move all the elements of a std::map移动 std::map 与移动 std::map 的所有元素
【发布时间】:2021-12-23 16:47:17
【问题描述】:
std::map<int, Obj> mp;
// insert elements into mp

// case 1
std::map<int, Obj> mp2;
mp2 = std::move(mp);

// case 2
std::map<int, Obj> mp3;
std::move(std::begin(mp), std::end(mp), std::inserter(mp3, std::end(mp3));

我对这两种情况感到困惑。它们完全一样吗?

【问题讨论】:

  • 第一个具有恒定时间复杂度,第二个具有nlogn时间复杂度。
  • 不,它们不一样。请注意,第二种情况下的目的地地图可能有点不同(例如有不同的顺序)。案例1超级快,案例2必须为mp3分配一些map内部结构。
  • 请注意,第一个副本只是将整个树从第一个映射移动到第二个,第一个(通常)保持为空,而第二个变体由于 std::move 的性质将第二个树中的节点保留为是,只是它们的内容被移动:假设std::map&lt;std::vector&lt;...&gt;&gt;,则向量的内容被移动,而第一个地图中的向量本身保持不变(通常为空)。

标签: c++ c++11 move stdmap c++-standard-library


【解决方案1】:

它们完全一样吗?

,他们不是!

第一个调用std::map4移动构造函数,移动操作将在类/数据结构级别完成。

[...]

  1. 移动构造函数。 在容器移动构造 (overload (4)) 之后,指向 other 的引用、指针和迭代器(结束迭代器除外)仍然有效,但引用现在位于 *this 中的元素。当前标准通过container.requirements.general 中的一揽子声明做出此保证,并且正在考虑通过LWG 2321 提供更直接的保证

复杂性

4) 常量。如果给定 alloc 且 alloc != other.get_allocator(),则为线性。


第二个std::move 来自&lt;algorithm&gt; header,它将元素(即键值对)移动到另一个映射。

  1. [first, last) 范围内的元素移动到另一个以d_first 开始的范围,从第一个开始,一直到最后一个 - 1。在此操作之后,已移动范围内的元素仍将包含适当类型的有效值,但不一定与移动之前的值相同。

复杂性

正是last - first移动作业。

【讨论】:

    【解决方案2】:

    不,它们不一样。

    • 案例 1 一次移动整个map 的内容。 map 的内部指针被“移动”到 mp2 - 映射中的 pair 均不受影响。
    • 案例 2 在地图中逐个移动pair。请注意,map Keyconst,因此它们不能被移动,而是被复制。 mp 仍将包含与以前一样多的元素 - 但其值处于不确定状态。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-05
      • 2014-03-10
      相关资源
      最近更新 更多