在std :: map中复制/移动键/值类型的要求?

时间:2013-07-11 21:16:33

标签: c++ c++11

这段代码让我困惑:

struct foo {
  int i;

  foo(int j) : i(j) {}

  foo(const foo &) = delete;
  foo(foo &&) = delete;
  foo &operator=(const foo&) = delete;
  foo &operator=(foo&&) = delete;
};

bool operator<(const foo &f1, const foo &f2)
{
  return f1.i < f2.i;
}

int main(int argc, char **argv)
{
  std::map<foo,int> f;
  std::map<foo,int> f2 = f; //error (as expected)
  std::map<foo,int> f3 = std::move(f); //no error (why?)
  return 0;
}

因为我没有得到错误,所以在移动地图时似乎没有创建关键对象(甚至没有将其他关键对象移入其中)。

为什么不呢?我可以根据C ++ 11标准依赖这种行为吗?

更一般地说,std::map键和值类型以及在什么条件下的复制/移动要求是什么?

2 个答案:

答案 0 :(得分:16)

将一张地图复制分配到另一张地图需要复制每个项目。由于您无法复制项目,因此无法复制 - 分配地图。

实际的地图对象在运行时是否为空是无关紧要的,因为它们完全是静态注意事项,完全由对象的类型决定。

(这就像在明确结果为整数时询问为什么sin(0)需要浮点单位。)

另一方面,移动整个地图很好,因为容器是基于节点的,并且没有实际值被突变,只是节点是。实际上,移动构造或移动分配基于节点的容器不需要元素可复制可移动可分配。

(对于以合适的方式管理动态内存的所有容器都应该如此,例如通过std::allocator<value_type>,但对std::array之类的东西来说当然不是这样,它会是有趣的是它是否适用于std::dynarray,并且正如@Jonathan Wakely指出的那样,如果分配方案无法移动节点批次。)

答案 1 :(得分:3)

没有错误,因为只移动了map,而不是map的元素。指向元素的指针