1

COMオブジェクトを管理するためのboost::intrusive_ptrの使用に関する記事を読みました。著者は、通常のCOMセマンティクスのスマートポインターの調整を処理するラッパークラスを示しています。これはクラスです:

template <typename T>
class WrapPtr
{
public:
    WrapPtr(boost::intrusive_ptr<T>& ref)
    : m_ref(ref), m_ptr(0)
    {
    }
   
    ~WrapPtr()
    {
        // The second parameter indicates that the reference count should not be incremented
        m_ref = boost::intrusive_ptr(m_ptr, false);
    }
   
    operator T**()
    {
        return &m_ptr;
    }
   
    operator void**()
    {
        // Some COM functions ask for a pointer to void pointer, such as QueryInterface
        return reinterpret_cast<void**>(&m_ptr);
    }
   
private:
    T* m_ptr;
    boost::intrusive_ptr<T> m_ref;
};

template <typename T>
WrapPtr<T> AttachPtr(boost::intrusive_ptr<T>& ref)
{
    return WrapPtr<T>(ref);
}

私が理解していないのはデストラクタです。現在のm_refオブジェクトを破棄します(Releaseもちろん呼び出しにつながります)が、m_ptrメンバーから構築された新しいintrusive_ptrを割り当てます。Wrapperクラスはintrusive_ptrのコピーを保持しており、それへの参照ではないため、デストラクタでこれが必要な理由がわかりません。呼び出し先がポイントされたオブジェクトを変更した場合、この変更はデストラクタが残された後に失われます。これはここのバグですか、それとも何かが足りませんか?

4

1 に答える 1

1

私がかつて見た同様の「安全なアドレスの」クラスでは、クラスにはintrusive_ptr<T>&実際のオブジェクト()ではなく、 intrusive_ptr参照()がありましたintrusive_ptr<T>。投稿したクラスは、実際にはクライアントのintrusive_ptrに影響を与えません。したがって、コードはバグがあるように見えます。個別のintrusive_ptrオブジェクトではなく、クライアントのintrusive_ptrへの参照を保持する必要があります。

template <typename T>
class WrapPtr
{
private:
    T* m_ptr;
    boost::intrusive_ptr<T>& m_ref;

    ...
};

編集:私はあなたの実際の質問に答えるのを忘れました:)

上記の修正により、デストラクタが行うことはより明確になります。つまり、演算子T**を呼び出すことによって設定されたポインタを保持するようにクライアントのintrusive_ptrを設定します。または演算子void **を使用して、それを「getter」メソッド(QueryInterfaceなど)に渡します。

于 2013-01-20T13:32:49.580 に答える