Есть ли цель в этом назначении перемещения _com_ptr_t? - PullRequest
1 голос
/ 27 сентября 2019

Итак, у нас есть этот код

_com_ptr_t& operator=(_com_ptr_t&& cp) throw()
{
    if (m_pInterface != cp.m_pInterface) {
        Interface* pOldInterface = m_pInterface;

        m_pInterface = cp.m_pInterface;
        cp.m_pInterface = nullptr;

        if (pOldInterface != nullptr) {
            pOldInterface->Release();
        }
    }
    return *this;
}

pOldInterface - это Release()d при назначении хода.Почему операции присваивания / конструктора перемещения не реализованы в виде свопов, которые позволяют Release() происходить естественным образом в деструкторе перемещенного объекта, просто используйте присваивание nullptr или Release(), чтобы вручную запустить его раньше?

Я всегда реализую перемещениеКонструкторы как операции обмена.Это плохая практика?

Мой код будет

_com_ptr_t& operator=(_com_ptr_t&& cp) throw()
{
    if (m_pInterface != cp.m_pInterface) {
        Interface* pOldInterface = m_pInterface;
        m_pInterface = cp.m_pInterface;
        cp.m_pInterface = pOldInterface;
        // or just std::swap(m_pInterface, cp.m_pInterface);
    }
    return *this;
}

Есть ли причина выбора MS _com_ptr_t?Этот вопрос также относится к любому назначению / конструктору перемещения, поэтому этот контекст более / менее актуален.Все дело в том, выпускаем ли мы данные или меняем их?

1 Ответ

2 голосов
/ 28 сентября 2019

Я всегда реализую конструкторы перемещения как операции подкачки.Это плохая практика?

Обычно отмечают плохую практику, но зависит от того, что делает Release() (в первом коде).Если Release() должен заботиться о любых связанных объектах при Interface движениях, реализация может отличаться от простой операции свопинга.

Для тривиального случая я лично предпочитаю std::exchange идиома (необходимо или более поздняя версия), что имеет смысл в операциях перемещения.

_com_ptr_t& operator=(_com_ptr_t&& cp) throw()
{
    if (m_pInterface != cp.m_pInterface)
    {
        m_pInterface = std::exchange(cp.m_pInterface, nullptr);
    }
    return *this;
}
...