92

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

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);

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

“除非另有说明,否则此类移出的对象应置于有效但未指定的状态。”

我从未发现任何“以其他方式指定”的实例。

虽然我觉得ver3有点迂回,更喜欢ver1,虽然vec3可以允许一些额外的优化,但另一方面很容易导致错误。

我的假设正确吗?

4

3 回答 3

109

从规范“有效但未指定的状态”的第 17.3.26 节:

一个未指定的对象状态,除了满足对象的不变量并且对象上的操作按照其类型指定的行为[示例:如果x类型的对象std::vector<int>处于有效但未指定的状态,x.empty()则可以无条件调用,并且x.front()可以调用仅当x.empty()返回 false。—结束示例]

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

clear,例如,没有先决条件。它会将对象返回到已知状态。因此,只需将其清除并正常使用即可。

于 2012-02-06T23:29:48.267 回答
16

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

成员函数对对象的clear()状态没有先决条件(当然,除了它是有效的),因此可以在移出对象上调用。另一方面,例如front()取决于容器不是空的,因此不能被调用,因为不能保证它是非空的。

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

于 2012-02-06T23:30:44.953 回答
-9

我不认为你可以对一个移动的对象做任何事情(除了销毁它)。

你不能使用它swap来获得移动的所有优势,但让容器处于已知状态吗?

于 2012-02-06T23:26:40.207 回答