Имеет ли смысл повторно использовать логику деструктора, используя std::swap в операторе присваивания перемещения?
Учтите следующее:
class Example : boost::noncopyable
{
HANDLE hExample;
public:
Example()
{
hExample = InitializeHandle();
}
~Example()
{
if (hExample == INVALID_HANDLE_VALUE)
{
return;
}
FreeHandle(hExample);
}
Example(Example && other)
: hExample(other.hExample)
{
other.hExample = INVALID_HANDLE_VALUE;
}
Example& operator=(Example &&other)
{
std::swap(hExample, other.hExample); //?
return *this;
}
};
Я думаю, что деструктор скоро будет работать с "другим", и поэтому мне не нужно снова реализовывать свою логику деструктора в операторе присваивания перемещения с помощью swap. Но я не уверен, что это разумное предположение. Это будет "хорошо"?
3 ответа
Все должно быть в порядке, но вряд ли это лучше, чем рекомендуемый метод передачи по значению, и в этом случае в этой ситуации будет использоваться конструктор перемещения.
Представьте себе следующее:
// global variables
Example foo;
struct bar {
void f() {
x = std::move(foo); // the old x will now live forever
}
Example x;
}
Подобная идиома copy-and-swap (или, в данном случае, move-and-swap) гарантирует, что деструктор будет запущен немедленно, что, по моему мнению, является лучшей семантикой.
Example& operator=(Example other) // other will be moved here
{
std::swap(hExample, other.hExample);
return *this;
} // and destroyed here, after swapping
Я думаю, что деструктор скоро будет работать на "другом"
Тогда ваше мышление ошибочно. Вы можете перемещаться с любого объекта, к которому у вас есть неконстантный доступ. И после этого объект может продолжать жить бесконечно долго.
Технически правильно поместить ваши текущие данные в старый объект. Но это не очень хорошая идея. Лучше использовать переменную стека:
Example& operator=(Example &&other)
{
Example temp(std::move(other)); //other is now empty.
std::swap(hExample, temp); //our stuff is in `temp`, and will be destroyed
return *thisl
}
Или еще лучше (если вы не используете Visual Studio) храните ваши вещи в оболочке, которая правильно поддерживает перемещение, и пусть сгенерированный компилятором конструктор перемещения сделает всю работу за вас.