这个 _com_ptr_t 移动任务有什么目的吗?

Is there a purpose to this _com_ptr_t move assignment?

所以我们有这段代码

_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;
}

pOldInterfaceRelease()d 移动分配。为什么移动 assignment/constructor 操作没有实现为交换,让 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 选择背后有什么原因吗?这个问题也适用于任何移动 assignment/constructor 所以这个上下文是 more/less 相关的。关键是我们是释放数据还是交换数据?

I always implement move constructors as swap operations. Is this bad practice?

通常会注意到一个不好的做法,但取决于 Release() 做了什么(在第一个代码中)。如果 Release() 必须在 Interface 移动时处理任何相关对象,则实现可能不同于简单的交换操作。

对于简单的情况,我个人更喜欢 std::exchange idiom (need 或更高版本),这在移动操作中是有意义的。

_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;
}