Конструктор перемещения

1,00
р.
Зачем нужен конструктор перемещения, если есть оператор перемещения:
operator=(T&&)

Ответ
Область использования
Конструктор и оператор перемещения используются компилятором в разных ситуациях:
конструктор перемещения применяется в местах, где объявление совпадает с определением (инициализацией) rvalue-ссылкой на экземпляр этого же класса, либо посредством direct initialization в конструкторе класса/структуры (если же определение произойдет с помощью lvalue-ссылки, то вызовется конструктор копирования) оператор перемещения применяется в местах, где экземпляр класса уже был ранее определен и к нему применяется operator =, который в качестве аргумента приминает rvalue-ссылку на экземпляр этого же класса (если же оператор принимает lvalue-ссылку , то вызовется оператор присваивания).
Про rvalue-ссылки можете почитать здесь, здесь и здесь.

Контрольный пример (для разъяснения отличия в работе данных конструкций)
#include
class Buffer { public: Buffer(const std::string& buff) : pBuff(nullptr) , buffSize(buff.length()) { pBuff = new char[buffSize] memcpy(pBuff, buff.c_str(), buffSize) }
~Buffer(){ destroy() }
Buffer(const Buffer& other) : pBuff(nullptr) , buffSize(other.buffSize) { pBuff = new char[buffSize] memcpy(pBuff, other.pBuff, buffSize) }
Buffer& operator=(const Buffer& other) { destroy() buffSize = other.buffSize pBuff = new char[buffSize] memcpy(pBuff, other.pBuff, buffSize) return *this }
Buffer(Buffer&& tmp) : pBuff(tmp.pBuff) , buffSize(tmp.buffSize) { tmp.pBuff = nullptr }
Buffer& operator=(Buffer&& tmp) { destroy() buffSize = tmp.buffSize pBuff = tmp.pBuff tmp.pBuff = nullptr return *this }
private: void destroy() { if (pBuff) delete[] pBuff }
char* pBuff size_t buffSize }
Buffer CreateBuffer(const std::string& buff) { Buffer retBuff(buff) return retBuff }
int main() { Buffer buffer1 = CreateBuffer("123") // срабатывает конструктор перемещения Buffer buffer2 = buffer1 // срабатывает конструктор копирования buffer2 = CreateBuffer("123") // срабатывает конструктор перемещения, затем оператор перемещения buffer2 = buffer1 // срабатывает оператор присваивания }

Дополнение
В C++11 каждый класс, помимо конструктора по умолчанию, имеет следующие 5 дефолтных операций:
конструктор копирования (copy constructor) оператор присваивания (copy assignment) конструктор перемещения (move constructor) оператор перемещения (move assignment) деструктор (destructor).
При определении одной из этих 5-ти операций рекомендуется явно указать (либо определить, либо объявить с помощью default или delete) все остальные, т.к. все эти 5 операций тесно связаны. Это будет способствовать лучшему пониманию семантики класса при чтении кода. Если явно определена одна из упомянутых 5-ти операций (в том числе с использованием default или delete), то:
недостающие операции копирования будут определены автоматически с поведением по умолчанию недостающие операции перемещения определены не будут.
Это следует учитывать при написании классов.