【问题标题】:Adding unmanaged / non managed member to managed class将非托管/非托管成员添加到托管类
【发布时间】:2018-03-19 00:28:59
【问题描述】:

感谢您的关注。我是一些 VS2013 代码的新手,它是 C++ 加上一些微软特定扩展的混合体。该代码有一个类似

的类
ref class Foo {
    Bar^ bar_; // somewhere else, bar_ = gcnew Bar...
};

现在我需要添加一个非托管成员,从在线搜索看来我可以做到

ref class Foo {
    Bar ^ bar_;
    Unmanaged* ptr_; // somewhere else, ptr = new Unmanaged();
    ~Foo() {
        this->!Foo();
    }
    !Foo() {
        delete ptr_;
        // do I need anything to deal with bar_?
    }
};

问题是:

1) 这个终结器/析构函数是要走的路吗?

2) 既然我明确地编写了终结器/析构函数,我还需要为 bar_ 写任何额外的东西吗?

3) 有更清洁的方法吗?

【问题讨论】:

    标签: c# c++ visual-c++ c++-cli


    【解决方案1】:

    1) 这个终结器/析构函数是要走的路吗?

    是的。

    2) 我需要为 bar_ 写一些额外的东西吗?

    从 sn-ps 中看不出什么。但是如果 Bar 类也是一次性的,那么您可能应该将 delete bar_; 添加到析构函数中。不是终结者。如果您将引用传递给其他代码,则不能确定此引用是最后一个仍在使用 Bar 对象的引用。

    3) 有更清洁的方法吗?

    没有。还有其他种方法可以做到这一点。例如,您可以考虑不添加析构函数。拥有一个给使用类的代码调用它的负担。通常是 C# 或 VB.NET 代码,它必须使用 using 语句或显式调用 Dispose()。请记住,他们经常忘记。或者没有好的方法来调用它。

    如果不希望此类代码创建大量 Foo 实例并且 Unmanaged 类仅使用一点内存,那么终结器可能就足够了。或者,如果 Foo 对象预计会在应用程序的整个生命周期中存在,这很常见,那么处置是没有意义的。即使它确实使用了大量内存,那么 GC::AddMemoryPressure() 也是一个不错的选择。让您的课程更易于使用。

    您可以考虑将非托管指针包装在它自己的类中,这样 Foo 就不再需要终结器了。按照 .NET 中 SafeHandle 类的模式,SafeBuffer 是最接近的匹配项。这往往是矫枉过正,但在 C++/CLI 包装器中,delete 失败尤其是您不想隐藏的。

    但你已经完成了工作。

    【讨论】:

    • 谢谢@hans-passant!自从我是纯 c++ 但对 VS2013 不熟悉后,只需再跟进一次。如何检查课程是否是一次性的?它们在声明中都显而易见吗?我还看到了诸如 POD(bool 等)、array<String^>^String^ 之类的东西,例如我无法找到 ref class array 的来源?
    • 当它实现 IDisposable 接口时。对象浏览器可以告诉你一个。 POD 从不这样做。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-14
    • 1970-01-01
    相关资源
    最近更新 更多