VC ++ / CLI:如何防止非托管对象超出范围时被销毁?

时间:2015-06-10 16:10:41

标签: .net visual-c++ c++-cli interop

我有一个第三方非托管C ++库,它有两个类,我们称之为ClassAClassBClassA有一个方法,我们称之为getTheB(),它返回ClassB的实例 - 它不返回指向实例的指针,而是实例本身。

我现在为ClassA编写了一个托管包装器,后者又有一个方法getTheB(),它返回一个包装ClassB的托管包装器。

第三方库中的原始ClassB对象必须通过其指针移交给我的托管包装器,如:

ThirdParty::ClassB db = delegateForClassA -> getTheB();
ManagedClassB^ mb = gcnew ManagedClassB(&db);

但是,当我的getTheB()包装器的ClassA包装完成并且范围结束时,ManagedClassB实例包含对第三方ClassB的悬空引用和调用后者的析构函数,在访问ClassB的方法时会产生有趣的结果。

在我的另一个问题中,我被告知以某种方式存储原始ClassB对象,但我不知道如何。

那么,如何让第三方ClassB实例保持活力?

2 个答案:

答案 0 :(得分:1)

您可以更改getTheB以返回堆分配的ClassB,也可以让ManagedClassB创建自己的db对象副本。

副本更新:

我假设ManagedClassB的构造函数看起来像

public ref class ManagedClassB
{
public:
    ManagedClassB(ClassB* p)
        : m_p(p) { }
...
private:
    ClassB* m_p;
};

您只需将其更改为

即可
public ref class ManagedClassB
{
public:
    ManagedClassB(const ClassB& b)
        : m_b(b) { }
...
private:
    ClassB m_b;
};

public ref class ManagedClassB
{
public:
    ManagedClassB(ClassB* p)
        : m_p(new ClassB(*p)) { }
...
private:
    ClassB* m_p;
};

答案 1 :(得分:0)

您应该在适合您使用的范围内分配数据库。你知道什么是最适合你的,无论是某个东西的静态成员,还是一个基本的全球,或者其他什么。只要您需要db,范围必须保持有效,并且在您完成操作后执行可能超出范围。