在可移动和不可复制的类上使用移动和交换习惯是否有意义

Fla*_*ame 5 c++ rvalue-reference assignment-operator copy-and-swap c++11

如果我有一个类如

class Foo{
public:
    Foo(){...}
    Foo(Foo && rhs){...}
    operator=(Foo rhs){ swap(*this, rhs);}
    void swap(Foo &rhs);
private:
    Foo(const Foo&);
// snip: swap code
};
void swap(Foo& lhs, Foo& rhs);
Run Code Online (Sandbox Code Playgroud)

如果我没有复制构造函数,是否有意义实现operator = by value和swap?它应该防止复制我的类对象Foo但允许移动.

这个类是不可复制的,所以我不能复制构造或复制分配它.

编辑

我用这个测试了我的代码,它似乎有我想要的行为.

#include <utility>
#include <cstdlib>
using std::swap;
using std::move;
class Foo{
public: Foo():a(rand()),b(rand()) {}
        Foo(Foo && rhs):a(rhs.a), b(rhs.b){rhs.a=rhs.b=-1;}
        Foo& operator=(Foo rhs){swap(*this,rhs);return *this;}
        friend void swap(Foo& lhs, Foo& rhs){swap(lhs.a,rhs.a);swap(lhs.b,rhs.b);}
private:
    //My compiler doesn't yet implement deleted constructor
    Foo(const Foo&);
private:
    int a, b;
};

Foo make_foo()
{
    //This is potentially much more complicated
    return Foo();
}

int main(int, char*[])
{
    Foo f1;
    Foo f2 = make_foo(); //move-construct
    f1 = make_foo(); //move-assign
    f2 = move(f1);
    Foo f3(move(f2));
    f2 = f3; // fails, can't copy-assign, this is wanted
    Foo f4(f3); // fails can't copy-construct

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

tem*_*def 5

移动和交换确实是合理的.如果禁用复制构造函数,那么调用此函数的唯一方法是使用移动构造函数构造参数.这意味着如果你写

lhs = rhs; // Assume rhs is an rvalue
Run Code Online (Sandbox Code Playgroud)

然后,operator =将使用移动构造函数初始化参数的构造函数,清空rhs并将参数设置为旧值rhs.然后呼吁swap交换lhs旧的价值和rhs旧的价值,留下lhs持有rhs的旧价值.最后,参数的析构函数触发,清理lhs旧的记忆.作为一个注释,这实际上不是移动和交换的复制和交换.

那说,你现在拥有的是不正确的.std::swap内部的默认实现将尝试使用移动构造函数来移动元素,这会导致无限递归循环.你必须超载std::swap以使其正常工作.

你可以网上看到这个在ideone.

有关更多信息,请参阅此问题及其对"四分之一规则"的讨论.

希望这可以帮助!