移动不带指针的构造函数

Move Constructor with no pointers

本文关键字:构造函数 指针 移动      更新时间:2023-10-16

我知道这个问题可能看起来非常基本。但我在任何地方都找不到一个带有指针的move构造函数的例子。

我有一个类,它包含一个向量对象变量。没有指向一个的指针。所以我的问题是:这是否意味着我不需要移动构造函数?或者我的实现是错误的,我应该使用指向向量的指针,然后使用移动构造函数?

感谢

如果您的类包含可移动对象(如向量),那么只需让编译器生成隐式移动操作。他们会做正确的事情,移动每个子对象。

如果您自己处理指向动态对象或其他非托管资源句柄的原始指针,则只需要编写自己的指针。最好的方法是有一个正确的可复制/可移动对象(如容器、智能指针或其他RAII类)来管理每一个;那么通过组合这些内容构建的复杂对象将隐含地具有正确的复制/移动语义。

(正如评论中所指出的:如果你的类声明了自己的析构函数或复制操作,那么它就不会得到隐式的移动操作;你需要定义自己的。但如果你遵循上面的建议,用不需要任何特殊处理的正确管理的类型来组合它,那么你就不需要声明这些东西。)

Move构造函数遵循与复制构造函数类似的准则。当您的类通过指针或其他脆弱的数据字段(套接字、数据库连接等)持有成员时,它是必需的,因此自动生成的一个可能会因为两次删除同一对象而扰乱内存布局。所以,如果没有任何指针字段,就不必编写move构造函数。

编译器生成的默认移动构造函数和移动附件将为类的每个成员调用移动构造函数/附件。

如果您的类只有原始成员,例如"char*buffer",则必须编写自己的移动操作。

如果您的类只有"托管成员"(例如"vector"),则类的默认移动操作是可以的,因为它将操作委派给每个成员。

例如,如果您的类具有混合了"原始成员"、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值,这样它的值就可以移动。