连续的存储容器和移动语义

时间:2014-11-20 22:55:18

标签: c++11 vector move semantics contiguous

容器如何既可以连续连接又可以同时支持移动语义?

std :: vector的一个例子: 当在左值上使用std :: move调用push_back()时:

std::vector<MyClass> v;

MyClass obj;
MyClass obj2;

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

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

MyClass obj;
MyClass obj2;

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

2 个答案:

答案 0 :(得分:2)

您只需要阅读有关移动语义的更多信息: - )

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

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

换句话说,对象本身在向量中创建的,只有它们的内容被移动(它意味着&#39;移动&# 39;每个类型的对象可能不同,因此移动构造函数的工作就是实际移动。)

请注意,即使使用obj,也可能无法调用移动构造函数 - 例如,可能没有移动构造函数,或者可能存在一个不是std::move的移动构造函数(其中)案例noexcept无法在不违反其异常安全保障的情况下在所有情况下使用它。)

答案 1 :(得分:0)

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

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