比较C++中移动和智能指针之间的习惯?

lin*_*bin 1 c++ move shared-ptr c++11

在C++ move11/14中,对象可以通过或者smark指针传输.

(1)这是一个例子move:

class MoveClass {
private:
    int *tab_;
    int alloc_;
    void Reset() {
        tab_ = nullptr;
        alloc_ = 0;
    }
    void Release() {
        if (tab_) delete[] tab_;
        tab_ = nullptr;
        alloc_ = 0;
    }

public:
    MoveClass() : tab_(nullptr), alloc_(0) {}
    ~MoveClass() {
        Release();
    }
    MoveClass(MoveClass && other) : tab_( other.tab_ ), alloc_( other.alloc_ ) {
        other.Reset();
    }
    MoveClass & operator=(MoveClass && other) {
        if (this == &other) return *this;
        std::swap(tab_, other.tab_);
        std::swap(alloc_, other.alloc_);
        return *this;
    }
    void DoSomething() { /*...*/ }
};
Run Code Online (Sandbox Code Playgroud)

当我们使用这个可移动的时候MoveClass,我们可以写这样的代码:

int main() {
    MoveClass a;
    a.DoSomething();  // now a has some memory resource
    MoveClass b = std::move(a);  // move a to b
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

总是写move-constructor/move-operator =很无聊,使用shared_ptr/unique_ptr有时会产生相同的效果,就像java,reference/pointer到处都是.

(2)这是一个例子:

class NoMoveClass {
private:
    int *tab_;
    int alloc_;
    void Release() {
        if (tab_) delete[] tab_;
        tab_ = nullptr;
        alloc_ = 0;
    }

public:
    NoMoveClass() : tab_(nullptr), alloc_(0) {}
    ~NoMoveClass() {
        Release();
    }
    MoveClass(MoveClass && other) = delete;
    MoveClass & operator=(MoveClass && other) = delete;
    void DoSomething() { /*...*/ }
};
Run Code Online (Sandbox Code Playgroud)

我们可以像这样使用它:

int main() {
    std::shared_ptr<NoMoveClass> a(new NoMoveClass());
    a->DoSomething();
    std::shared_ptr<NoMoveClass> b = a; // also move a to b by copy pointer.
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

总是使用第二个是一个好习惯吗?

为什么很多图书馆,STL使用第一个,而不是第一个?

Ap3*_*p31 6

总是写move-constructor/move-operator =很无聊

几乎不需要编写自己的移动构造函数/赋值,因为(正如你所提到的)C++为你提供了许多基本的资源管理器 - 智能指针,容器,智能锁等.

通过依赖类中的那些,您可以启用默认移动操作,从而产生最小的代码大小以及正确的语义:

class MoveClass {
private:
    std::vector<int> data;
public:
    void DoSomething() { /*...*/ }
};
Run Code Online (Sandbox Code Playgroud)

现在您可以像在(1)中一样使用您的类,或者在其他类中使用您的类,您可以确定它具有移动语义,并且您可以在尽可能少的代码中完成它.

关键是通常只需要为STL可能已经涵盖的最低级别的类实现移动操作,或者如果需要一些奇怪的特定行为 - 两种情况都应该非常罕见并且不会导致"始终写入移动 - 构造/移动运营商=".

还要注意虽然方法(1)是不必要的冗长,但(2)只是不可接受 - 你有一个资源管理类不能完成它的工作,因此你必须将它包装在代码中的任何地方的智能指针中,它更难理解并最终产生比(1)更多的代码