C++/CLI 包裝返回 std::shared_ptr 的函式
我目前正在使用 C++/CLI 包裝一個 C++ 類,以實現 .NET 互操作性,遵循在託管類中保存本機指針的標準過程。在一個例子中,我有一個本地類,它的功能如下:
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
shared_ptr是本機類型,託管對像不能具有完整的本機子對象。但是,正如您所注意到的,託管對象可以具有指向本機對象的指針。您需要的是一個指向 a 的指針
shared_ptr,它將被視為對該BaseChannel對象的引用並防止它被過早釋放。當然,使用智能指針而不是 raw 有很多理由
shared_ptr<BaseChannel>*。我寫了一個應該合適的智能指針,你可以在 codereview.stackexchange.com 上找到它:“scoped_ptr for C++/CLI(確保託管對象正確釋放擁有的本機對象)”範例(未經編譯測試):
ref class ChannelUser { clr_scoped_ptr<shared_ptr<BaseChannel>> chan_ptr; public: ChannelUser( shared_ptr<BaseChannel>& chan ) : chan_ptr(new shared_ptr<BaseChannel>(chan)) {} };這會自動實現
IDisposable並刪除shared_ptrwhenDispose或 finalizer 執行,從而減少BaseChannel.
這是一個託管的
shared_ptr<T>. 您可以直接從 a 分配給它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(); } };