3

一个容器如何既是连续的又支持移动语义呢?

std::vector 的示例:当 push_back() 使用 std::move 对左值调用时:

std::vector<MyClass> v;

MyClass obj;
MyClass obj2;

vt.push_back(std::move(obj));
vt.push_back(std::move(obj2));

obj 和 obj2 不一定在内存中彼此相邻分配。现在由于向量必须将其元素放在连续的内存中,在这种情况下移动语义将如何工作?在我看来,它必须将 obj2 复制到向量 v 的连续内存区域(在 obj 旁边),否则将无法满足连续性要求。但这需要一个副本,而不是移动。那么上面和这个有什么区别呢?:

MyClass obj;
MyClass obj2;

vt.push_back(std::move(obj));
vt.push_back(obj2);
4

2 回答 2

2

你只需要阅读更多关于移动语义的内容:-)

移动对象不会改变对象本身的地址。它仅调用object 的另一个实例的移动构造函数(或赋值运算符等,取决于上下文),该实例被传递给要移动的对象。

在此示例中,向量确实MyClass在其内部存储中创建了两个对象,每个push_back. 但是对于第一个,它不是调用复制构造函数并传递obj(via MyClass const&),而是调用移动构造函数并将右值引用 ( MyClass&&) 传递给obj. 然后由该构造函数将obj对象的内容移动到向量内的内容中。

换句话说,对象本身在向量中创建的,并且仅移动了它们的内容(“移动”对象的含义可能因每种类型而异,因此移动构造函数的工作是进行实际移动)。

请注意,即使使用std::move,也可能不会调用移动构造函数——例如,可能没有一个,或者可能没有一个noexcept(在这种情况下std::vector,不能在所有情况下都使用它而不违反其异常安全保证) )。

于 2014-11-20T23:02:45.877 回答
0

std::move是一个演员,它是一个无条件的演员,如果你没有使用正确的语义,它很容易在副本中衰减。

换句话说,除了类型本身并不能保证你移动语义之外,写作std::move并不能保证你的任何东西。T&&

于 2014-11-20T23:03:39.970 回答