我知道这个问题可能看起来非常基本。但我无法在任何地方找到带有无指针的移动构造函数的示例。
我有一个包含矢量对象变量的类。不是一个指针。所以我的问题: 这是否意味着我不需要移动构造函数?或者我的实现是错误的,我应该使用指向向量的指针,然后使用移动构造函数?
谢谢
答案 0 :(得分:11)
如果您的类包含可移动对象(例如矢量),那么只需让编译器生成隐式移动操作。他们会做正确的事情,移动每个子对象。
如果你自己处理动态对象或其他非托管资源句柄的原始指针,你只需编写自己的代码。最好的方法是使用正确的可复制/可移动对象(例如容器,智能指针或其他RAII类)来管理其中的每一个;然后,通过组合这些构建的复杂对象将隐式具有正确的复制/移动语义。
(如评论中所述:如果你的类声明自己的析构函数或复制操作,那么它将不会获得隐式移动操作;你需要定义自己的。但是如果你按照上面的建议,编写它来自正确管理的类型,不需要任何特殊处理,那么你不需要声明任何这些东西。)
答案 1 :(得分:3)
移动构造函数遵循与复制构造函数类似的指导原则。当您的类通过指针或其他脆弱的数据字段(套接字,数据库连接等)保存成员时,它是必需的,因此自动生成的可能会通过删除相同的对象两次来搞乱内存布局。因此,如果您没有任何指针字段,则不必编写移动构造函数。
答案 2 :(得分:1)
编译器生成的默认移动构造函数和移动停止将为类的每个成员调用move constructor / asignment。
如果您的类只有原始成员,例如“char * buffer”,则必须编写自己的移动操作。
如果您的班级只有“托管成员”,例如“向量”,那么您的默认移动操作就可以了,因为它会将操作委托给每个成员。
如果您的类具有与“原始成员”,vector和int *混合的“托管成员”,则您的移动操作将必须手动移动原始资源并调用托管对象的移动操作:
class MyObject {
public:
// ...
MyObject(MyObject&& other) : vector1(std::move(other.vector1)) {
// We use vector's move constructor ^
// and then move ourself the char* buffer
buffer1 = other.buffer1;
other.buffer1 = nullptr;
}
MyObject& operator=(MyObject&& other) {
// We use vector's move asignment operator
vector1= std::move(other.vector1);
// and then move ourself the char* buffer
std::swap(buffer1,other.buffer1);
return *this;
}
//...
private:
vector<char> vector1;
char * buffer1;
};
需要std :: move(other.vector1)因为里面,其他函数other.vector1是左值。我们必须告诉编译器我们稍后不会在函数代码中使用vector1值,因此可以移动它的值。