C++/CLI包装返回std::shared\u ptr的函数 我现在在C++中使用C++/CLI类来封装.NET的互操作性,这是在托管类中保存一个本地指针的标准过程。在一个实例中,我有一个本机类,其函数如下: std::shared_ptr<BaseChannel> channelData(const int RunNumber);

C++/CLI包装返回std::shared\u ptr的函数 我现在在C++中使用C++/CLI类来封装.NET的互操作性,这是在托管类中保存一个本地指针的标准过程。在一个实例中,我有一个本机类,其函数如下: std::shared_ptr<BaseChannel> channelData(const int RunNumber);,.net,c++-cli,wrapper,shared-ptr,mixed-mode,.net,C++ Cli,Wrapper,Shared Ptr,Mixed Mode,因为共享_ptr在通过引用传递给托管类时其引用计数没有增加,这是否意味着 只要这个共享的ptr在 范围,它指向的对象将 仍然存在,因为它的引用 计数将至少为1 ??(ref)共享\u ptr是本机类型,托管对象不能有完整的本机子对象 但是,正如您所注意到的,托管对象可以有指向本机对象的指针。您需要的是一个指向共享\u ptr的指针,该指针将作为对BaseChannel对象的引用,并防止其过早释放 当然,使用智能指针而不是原始的共享\u ptr*有很多原因。我写了一个智能指针,它应该是合适的,你可

因为共享_ptr在通过引用传递给托管类时其引用计数没有增加,这是否意味着

只要这个共享的ptr在 范围,它指向的对象将 仍然存在,因为它的引用 计数将至少为1


??(ref)

共享\u ptr是本机类型,托管对象不能有完整的本机子对象

但是,正如您所注意到的,托管对象可以有指向本机对象的指针。您需要的是一个指向
共享\u ptr
的指针,该指针将作为对
BaseChannel
对象的引用,并防止其过早释放

当然,使用智能指针而不是原始的
共享\u ptr*
有很多原因。我写了一个智能指针,它应该是合适的,你可以在codereview.stackexchange.com上找到它:


示例(未经编译测试):

ref类ChannelUser
{
clr_范围_ptr chan_ptr;
公众:
ChannelUser(shared_ptr&chan):chan_ptr(new shared_ptr(chan)){}
};

这会自动实现
IDisposable
,并在
Dispose
或终结器运行时删除
shared_ptr
,从而减少
BaseChannel
上的引用计数。您可以直接从
共享\u ptr
分配给它,它将获取一个副本,当托管对象被GC’d或disposed时,它将删除该副本

示例:

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;
m_shared_ptr cupCake0(new CupCake());
m_shared_ptr cupCake1=新纸杯蛋糕();
m_shared_ptr cupCake2=shared_ptr(new CupCake());
m_shared_ptr cupCake3=使_共享();
共享杯4=(共享杯3);
代码:

#pragma一次
#包括
模板
公共参考类m_共享\u ptr密封
{
std::共享的ptr*pPtr;
公众:
m_共享_ptr()
:pPtr(新std::shared_ptr())
{}
m_共享_ptr(T*T){
pPtr=新标准::共享ptr(t);
}
m_shared_ptr(标准::shared_ptr t){
pPtr=新标准::共享ptr(t);
}
m_共享\u ptr(常数m_共享\u ptr%t){
pPtr=新标准::共享ptr(*t.pPtr);
}
!m_共享_ptr(){
删除pPtr;
}
~m_共享_ptr(){
删除pPtr;
}
操作员std::共享的_ptr(){
返回*pPtr;
}
m_共享_ptr%运算符=(T*ptr){
删除pPtr;
pPtr=新标准::共享ptr(ptr);
归还*这个;
}
T*运算符->(){
return(*pPtr.get();
}
无效重置(){
pPtr->reset();
}
};

+1-你能提供一个如何在你的回答中使用你的
clr\u scoped\u ptr
的例子吗?@Seth:已经完成了,希望这有帮助。如果发现任何重大错误,请告诉我。引用计数会增加(一次是通过ChannelUser ctor初始值设定项中的
spBaseChannel
的构造函数增加,一次是通过
new shared_ptr
增加)。。。但是当
std::shared_ptr
不是线程安全时,这些东西就不会是线程安全的。@Ben:我更新了最后一个问题,以恰当地表示我的担忧。然而,我认为你在之前的评论中已经回答了这个问题。ChannelUser ctor-initializer.awesome答案中的ref计数器增加。被低估了。m_shared_ptr的赋值运算符没有先删除p,这不是内存泄漏吗?我想你是对的,请随意编辑并修复这个答案。我想出了一些我需要的附加方法
://用于访问共享_ptr成员,如'use_count'const std::shared_ptr&get(){return*pPtr;}//当传递到另一个托管对象std::shared_ptr*share(){return new std::shared_ptr(*pPtr)}时非常有用//允许通过std::make_shared m_ptr%operator=(const std::shared_ptr&t){delete pPtr pPtr=new std::shared_ptr(t);return*this;}~
Brilliant本人就要写这样的东西了。谢谢你为我节省了一些时间!:D
ref class ChannelUser
{
    clr_scoped_ptr<shared_ptr<BaseChannel>> chan_ptr;

public:
    ChannelUser( shared_ptr<BaseChannel>& chan ) : chan_ptr(new shared_ptr<BaseChannel>(chan)) {}
};
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();
    }
};