重用移动的容器?

ron*_*nag 78 c++ move-semantics c++11

重用移动容器的正确方法是什么?

std::vector<int> container;
container.push_back(1);
auto container2 = std::move(container);

// ver1: Do nothing
//container2.clear(); // ver2: "Reset"
container = std::vector<int>() // ver3: Reinitialize

container.push_back(2);
assert(container.size() == 1 && container.front() == 2);
Run Code Online (Sandbox Code Playgroud)

从我在C++ 0x标准草案中读到的内容; ver3似乎是正确的方法,因为移动后的对象在a中

"除非另有规定,否则此类移动物体应处于有效但未指明的状态."

我从来没有找到任何"以其他方式指定"的实例.

虽然我发现ver3有点回旋并且会有更多首选ver1,虽然vec3可以允许一些额外的优化,但另一方面很容易导致错误.

我的假设是否正确?

Nic*_*las 92

从规范"有效但未指明的国家"的第17.3.26节:

一个未指定的对象状态,除了满足对象的不变量,对象上的操作表现为其类型的指定[示例:如果x类型的对象std::vector<int>处于有效但未指定的状态,x.empty()可以无条件地调用,并且x.front()可以调用只有x.empty()返回false. - 末端的例子]

因此,对象是实时的.您可以执行任何不需要前提条件的操作(除非您先验证前提条件).

clear例如,没有先决条件.它会将对象返回到已知状态.所以只需清除它并正常使用它.

  • @ronag:1)如果容器处于有效状态,则调用`clear`是有效的.2)当容器_was_处于未指定状态时,调用`clear`会将容器置于指定状态,因为它在标准中强制要求后置条件(§23.2.3表100).`std :: vector <T>`有一个类不变量,`push_back()`总是有效的(只要`T`是`CopyInsertable`). (4认同)
  • @ronag:open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3241.html 引用了国家机构对“空而不空”的评论之一。国家机构的评论是不正确的。N3241 没有提出这样的状态。如果 std::container 的实现确实有一个由移动导致的“比空更空”的状态,那么该状态必须是一个有效状态(即,您可以对该对象执行任何不需要先决条件的操作)。 (3认同)
  • 在标准中的哪里可以阅读有关 std::vector 方法的“先决条件”? (2认同)
  • 我发现以下内容很有意思,http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3241.html,他们写道"容器可以'空出'而不是空'". (2认同)

Gri*_*zly 10

处于有效但未定义状态的对象基本上意味着虽然不保证对象的确切状态,但它是有效的,因此只要它们不依赖于成员函数(或非成员函数),它们就能保证工作.具有某种状态的物体.

clear()memberfunction对对象的状态没有先决条件(其他然后它是有效的,当然),因此可以从对象移动调用.另一方面,例如front()取决于容器不是空的,因此不能被调用,因为它不能保证是非空的.

因此ver2和ver3都应该都没问题.