6

私は現在、マネージ クラスでネイティブ ポインターを保持する標準プロセスに従って、.NET 相互運用性のために C++/CLI で C++ クラスをラップしています。ある例では、次のような機能を持つネイティブ クラスがあります。

std::shared_ptr<BaseChannel> channelData(const int RunNumber);

のラッパー クラスの作成を既に開始していますBaseChannel。ただし、生のポインターをマネージド クラスのコンストラクターに渡すと、マネージド クラスが指すオブジェクトの有効期間は保証されません。つまり、shared_ptr がスコープ外になる可能性があり、オブジェクトが削除され、マネージ クラスがダングリング ポインターを保持したままになります。

この状況の一般的な解決策は何ですか?

アップデート

@Ben: したがって、上記の質問でメソッドを保持するクラスを次のようにラップします (それが呼び出されたネイティブ クラスにNodeあり、NodeRef と呼ばれるマネージド クラスにラップされているとしましょう:

ChannelUser^ NodeRef::ChannelData(int runNumber)
{
    // mpNode is native class pointer of type Node held in managed class
    // wrapper called NodeRef
    std::shared_ptr<BaseChannel> spBaseChannel = mpNode->channelData(runNumber);

    // ChannelUser is using clr_scoped_ptr to hold the shared_ptr
    ChannelUser^ channelUser = gcnew ChannelUser(spBaseChannel);
    return channelUser;
}

shared_ptr は参照によってマネージド クラスに渡されるため、参照カウントが増加していないため、ということですか?

この shared_ptr がスコープ内にある限り、参照カウントが少なくとも 1 であるため、それが指すオブジェクトは引き続き存在します。

? (ref C++ - std::shared_ptr または boost::shared_ptr への参照を渡す)

4

2 に答える 2

15

これがマネージドshared_ptr<T>です。から直接割り当てることができshared_ptr、管理対象オブジェクトが GC または破棄されたときに削除されるコピーを取得します。

例:

m_shared_ptr<CupCake> cupCake0(new CupCake());
m_shared_ptr<CupCake> cupCake1 = new CupCake();
m_shared_ptr<CupCake> cupCake2 = shared_ptr<CupCake>(new CupCake());
m_shared_ptr<CupCake> cupCake3 = make_shared<CupCake>();
shared_ptr<CupCake> cupCake4 = (shared_ptr<CupCake>)cupCake3;

コード:

#pragma once

#include <memory>

template <class T>
public ref class m_shared_ptr sealed
{
    std::shared_ptr<T>* pPtr;

public:
    m_shared_ptr() 
        : pPtr(new std::shared_ptr<T>()) 
    {}

    m_shared_ptr(T* t) {
        pPtr = new std::shared_ptr<T>(t);
    }

    m_shared_ptr(std::shared_ptr<T> t) {
        pPtr = new std::shared_ptr<T>(t);
    }

    m_shared_ptr(const m_shared_ptr<T>% t) {
        pPtr = new std::shared_ptr<T>(*t.pPtr);
    }

    !m_shared_ptr() {
        delete pPtr;
    }

    ~m_shared_ptr() {
        delete pPtr;
    }

    operator std::shared_ptr<T>() {
        return *pPtr;
    }

    m_shared_ptr<T>% operator=(T* ptr) {
        delete pPtr;
        pPtr = new std::shared_ptr<T>(ptr);
        return *this;
    }

    T* operator->() {
        return (*pPtr).get();
    }

    void reset() {
        pPtr->reset();
    }
};
于 2012-10-01T13:40:50.030 に答える
7

shared_ptrはネイティブ タイプであり、マネージド オブジェクトは統合ネイティブ サブオブジェクトを持つことはできません。

ただし、お気づきのように、マネージド オブジェクトはネイティブ オブジェクトへのポインターを持つことができます。必要なのは へのポインターですshared_ptr。これは、オブジェクトへの参照としてカウントされ、BaseChannel時期尚早に解放されないようにします。

もちろん、 raw の代わりにスマート ポインターを使用する理由はたくさんありますshared_ptr<BaseChannel>*。適切なはずのスマート ポインターを作成しました。codereview.stackexchange.com で見つけることができます


例 (コンパイルはテストされていません):

ref class ChannelUser
{
    clr_scoped_ptr<shared_ptr<BaseChannel>> chan_ptr;

public:
    ChannelUser( shared_ptr<BaseChannel>& chan ) : chan_ptr(new shared_ptr<BaseChannel>(chan)) {}
};

これにより、 whenまたはファイナライザーの実行が自動的に実装IDisposableおよび削除され、 .shared_ptrDisposeBaseChannel

于 2011-05-30T05:22:31.500 に答える