Мне известно, что в конструкторе перемещения / перегруженном назначении вы должны установить ссылки RValue, которые ссылаются на указатели на nullptr (в конце), чтобы избежать освобождения этого ресурса.
Вы не делаете.Это обычная модель, но она не является фундаментальной для того, как работает семантика перемещения.Что вам нужно сделать, так это настроить все так, чтобы уничтожение перемещенного объекта не испортило перемещенный объект.В случае указателей, которые деструктор собирается освободить, установка их на nullptr
является очевидным выбором, но с отдельным элементом bool m_hasBeenMovedFrom
, установленным в значение true, также будет работать, как если бы указатель указывал на вновь выделенный объектобъект.
Важно, однако, что rvalue ссылки сами ничего подобного не делают.Ссылки Rvalue - это просто вариант ссылок с немного отличающейся семантикой связывания от ссылок lvalue.Они не удаляют вещи так, как это делают ссылки lvalue.
В опубликованном вами коде конструктор получает ссылку на rvalue на объект и сохраняет указатель на этот объект.Это опасно, потому что вы можете сделать что-то вроде Foo f(3)
(или, поскольку это не-explicit
конструктор с одним аргументом, даже просто передать 3
функции, ожидающей Foo
), которая будет хранить указатель наистекающее значение.С другой стороны, если переданный объект гарантированно переживет Foo
, все будет в порядке, но если вам требуется, зачем использовать ссылку на rvalue?
В целом, в то время как код, который вы показали само по себе не имеет неопределенного поведения, абсолютно требует того, что UB произойдет при использовании класса.Смысл ссылки на rvalue - «этот объект скоро исчезнет, поэтому не стесняйтесь воровать его вещи».У int
нет никаких вещей, так что это бесполезно ... и, так как его уже нет, вы не хотите держать указатель на него.
Кстати, вы часто будете видетьстандартные библиотечные функции (и другие функции!) вида template<typename T> someFunc(T && arg)
.Это не ссылка на значение, а "ссылка для пересылки", или "универсальная ссылка", о которой вам расскажет множество страниц (но эта моя любимая).Главное, что здесь нужно помнить, это то, что T &&
будет действовать как ссылка на rvalue только в том случае, если ей дано значение rval, и что сама функция должна быть осторожна, чтобы не безоговорочно обрабатывать ее как ссылку на rvalue.