简体   繁体   中英

Swapping class with unique_ptr

#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);
}

This code does not work - fails with a wall of template errors saying no matching function for call to 'swap(A&, A&)' . Why? Deleting the second constructor helps, but I need it in other code. I guessed it could be connected with automatical deleting of some constructors when other are defined, but manually adding move constructor does not help either. How can I fix this?

std::swap() requires its arguments to be move-constructible and move-assignable .

Given:

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

A is swappable, thanks to the implicitly defined move-constructor and move-assignment operators.

But, given:

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

By declaring a user defined copy constructor, you're inhibiting the implicit definition of A 's move constructor and move assignment operator (and by having a non-assignable-copyable member, you're inhibiting the implicit generation of A 's copy constructor and copy assignment operator).

To make A swappable again, you need to either user-define both (*):

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

or neither, and just add proper copy-assignment:

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

but, this will probably defeat your original intent of avoiding deep copies on swap, so you'll probably end up defining all of them anyway.


(*) noexcept specifications omitted just for brevity ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM