Dot-Net

C++/CLI 包裝返回 std::shared_ptr 的函式

  • March 11, 2015

我目前正在使用 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

? (參考C++ - 傳遞對 std::shared_ptr 或 boost::shared_ptr 的引用

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();
   }
};

引用自:https://stackoverflow.com/questions/6172361