将类与unique_ptr交换

Swapping class with unique_ptr

本文关键字:ptr 交换 unique      更新时间:2023-10-16
#include <memory>
#include <algorithm>
using namespace std;
class A {
public:
    unique_ptr<int> u;
    A(){}
    A(const A& other): u(new int(*other.u)){} // If I comment this out, it works.
    // A(A&&){} // This does not help.
};
int main() {
    A a;
    A b = a;
    swap(a, b);
}

此代码不起作用 - 失败,模板错误墙说no matching function for call to ‘swap(A&, A&)’。为什么?删除第二个构造函数会有所帮助,但我在其他代码中需要它。我猜它可能与定义其他构造函数时自动删除某些构造函数有关,但手动添加移动构造函数也无济于事。我该如何解决这个问题?

std::swap()要求其参数是可移动构造的可移动可分配的

鉴于:

struct A {
    unique_ptr<int> u;
    A();
};

A是可交换的,这要归功于隐式定义的移动构造函数和移动赋值运算符。

但是,鉴于:

struct A {
    unique_ptr<int> u;
    A();
    A(A const&);
};

通过声明用户定义的复制构造函数,您将禁止A的移动构造函数和移动赋值运算符的隐式定义(并且通过拥有不可分配可复制的成员,您将禁止隐式生成A的复制构造函数和复制赋值运算符(。

要使A再次可交换,您需要同时定义两者(*(:

struct A {
    unique_ptr<int> u;
    A();
    A(A const&);
    A(A&&);
    A& operator=(A&&);
};

或者两者都不是,只需添加适当的复制分配:

struct A {
    unique_ptr<int> u;
    A();
    A(A const&);
    A& operator=(A const&);
};

但是,这可能会破坏您在 Exchange 上避免深度副本的初衷,因此您最终可能会定义所有这些副本。


(*( 否,仅为简洁起见省略了规格...