C++/CLI包装返回std :: shared_ptr的函数

Set*_*eth 3 .net mixed-mode c++-cli wrapper shared-ptr

我目前正在使用C++/CLI包装一个C++类,用于.NET互操作性,遵循在托管类中保存本机指针的标准过程.在一个实例中,我有一个本机类,其功能如下:

std::shared_ptr<BaseChannel> channelData(const int RunNumber);
Run Code Online (Sandbox Code Playgroud)

我已经开始为它创建一个包装类BaseChannel.但是,如果我将原始指针传递给托管类的构造函数,则无法保证托管类指向的对象的生命周期.即shared_ptr可能超出范围,对象将被删除,托管类将保留一个悬空指针.

这种情况的常见解决方案是什么?

UPDATE

@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;
}
Run Code Online (Sandbox Code Playgroud)

因为shared_ptr没有增加引用计数,因为它通过引用传递给托管类,这是否意味着

只要此shared_ptr在范围内,它指向的对象仍然存在,因为它的引用计数至少为1

?(ref C++ - 将引用传递给std :: shared_ptr或boost :: shared_ptr)

chi*_*tom 11

这是一个托管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;
Run Code Online (Sandbox Code Playgroud)

码:

#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();
    }
};
Run Code Online (Sandbox Code Playgroud)

  • 我提出了一些我需要的其他方法`://用于访问shared_ptr成员,例如'use_count'const std :: shared_ptr <T>&get(){return*pPtr; } //在传递给另一个托管对象时很有用std :: shared_ptr <T>*share(){return new std :: shared_ptr <T>(*pPtr); } //允许通过std :: make_shared进行赋值m_shared_ptr <T>%operator =(const std :: shared_ptr <T>&t){delete pPtr; pPtr = new std :: shared_ptr <T>(t); 返回*这个; } ~` (3认同)

Ben*_*igt 6

shared_ptr 是本机类型,托管对象不能具有完整的本机子对象.

但是,正如您所注意到的,托管对象可以具有指向本机对象的指针.你需要的是一个指向a的指针shared_ptr,它将被视为BaseChannel对象的引用并防止它过早被释放.

当然,有很多理由使用智能指针而不是原始指针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)) {}
};
Run Code Online (Sandbox Code Playgroud)

这会自动实现IDisposable并删除shared_ptr何时Dispose或终结器运行,从而减少对引用的引用计数BaseChannel.