Во-первых, есть общий совет, который гласит, что вам вообще не следует писать конструктор копирования / перемещения, оператор присваивания или деструктор, а вместо этого составляет ваш класс высокого уровня. -качественные компоненты, которые, в свою очередь, обеспечивают их, позволяя сгенерированным по умолчанию функциям делать правильные вещи. (Обратный смысл в том, что если вам нужно написать какой-либо из них, вам, вероятно, придется написать все из них.)
Таким образом, вопрос сводится к тому, "какой класс компонентов с одной ответственностью может использовать преимущества семантики перемещения?" Общий ответ: все, что управляет ресурсом . Дело в том, что конструктор / присваиватель перемещения просто переустанавливает ресурс для нового объекта и лишает законной силы старый, тем самым избегая (предполагаемого дорогого или невозможного) нового выделения и глубокого копирования ресурса.
Главный пример - это все, что управляет динамической памятью, где операция перемещения просто копирует указатель и устанавливает нулевой указатель старого объекта (поэтому деструктор старого объекта ничего не делает). Вот наивный пример:
class MySpace
{
void * addr;
std::size_t len;
public:
explicit MySpace(std::size_t n) : addr(::operator new(n)), len(n) { }
~MySpace() { ::operator delete(addr); }
MySpace(const MySpace & rhs) : addr(::operator new(rhs.len)), len(rhs.len)
{ /* copy memory */ }
MySpace(MySpace && rhs) : addr(rhs.addr), len(rhs.len)
{ rhs.len = 0; rhs.addr = 0; }
// ditto for assignment
};
Ключ в том, что любой конструктор копирования / перемещения будет выполнять полное копирование переменных-членов; только когда эти переменные сами являются дескрипторами или указателями на ресурсы, вы можете избежать копирования ресурса из-за соглашения о том, что перемещенный объект больше не считается допустимым и вы можете воровать у него. Если украсть нечего, то переезд не принесет никакой пользы.