Имеет ли смысл повторно использовать логику деструктора, используя std :: swap в операторе присваивания перемещения? - PullRequest
2 голосов
/ 17 марта 2012

Рассмотрим следующее:

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 ]

7 голосов
/ 17 марта 2012

Представьте себе следующее:

// 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
5 голосов
/ 17 марта 2012

Все должно быть в порядке, но едва ли лучше, чем рекомендуемый метод передачи по значению , и в этом случае в этой ситуации будет использоваться конструктор перемещения.

2 голосов
/ 17 марта 2012

Я думаю, что деструктор скоро будет работать на "другом"

Тогда ваше мышление ошибочно.Вы можете перемещаться с любого объекта, к которому у вас есть неконстантный доступ.И после этого объект может продолжать жить бесконечно долго.

Технически *1007* правильно поместить ваши текущие данные в старый объект.Но это не очень хорошая идея.Лучше использовать переменную стека:

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), храните ваши вещи в оболочке, которая правильно поддерживает перемещение, и пусть сгенерированный компилятором конструктор перемещения выполняетработа для вас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...