logo

C++ - movable vs copyable

A movable type = can be initialized and assigned from temporaries.

A copyable type = can be initialized or assigned from any other object of the same type.

Copy behavior is defined by the copy constructor and the copy-assignment operator. E.g.

Move behavior is defined by the move constructor and the move-assignment operator.

class Foo {
 public:
  Foo(const Foo& arg);             // copy constructor
  Foo(Foo&& arg);                  // move constructor
  Foo& operator=(const Foo& rhs);  // copy assignment operator
  Foo& operator=(Foo&& rhs);       // move assignment operator
  ...
};

A copyable example:

class Foo {
 public:
  Foo(const Foo& other) = default;
  Foo& operator=(const Foo& other) = default;
};

A move only example:

class Foo {
 public:

  // delete copy constructor and copy-assignment operator
  Foo(const Foo&) = delete;
  Foo& operator=(const Foo&) = delete;

  // default move constructor and move-assignment operator
  Foo(Foo&& other) = default;
  Foo& operator=(Foo&& other) = default;
};

A non-copyable and non-movable example:

class Foo {
 public:

  // delete copy constructor and copy-assignment operator
  Foo(const Foo&) = delete;
  Foo& operator=(const Foo&) = delete;

  // delete move constructor and move-assignment operator
  Foo(Foo&& other) = delete;
  Foo& operator=(Foo&& other) = delete;
};

Examples:

  • movable but not copyable: e.g. std::unique_ptr<int>
  • movable and copyable: int and std::string, for int, the move and copy operations are the same; for std::string, there exists a move operation that is less expensive than a copy.

Can be generated by the compiler, either implicitly or with = default.