gpt4 book ai didi

garbage-collection - 为什么 GC 不会自动处理我类(class)的成员?

转载 作者:行者123 更新时间:2023-12-02 02:36:43 25 4
gpt4 key购买 nike

当我在 VS2008 中构建以下 C++/CLI 代码时,显示代码分析警告 CA1001。

ref class A
{
public:
A() { m_hwnd = new HWND; }
~A() { this->!A(); }
protected:
!A() { delete m_hwnd; }
HWND* m_hwnd;
};

ref class B
{
public:
B() { m_a = gcnew A(); }
protected:
A^ m_a;
};

warning: CA1001 : Microsoft.Design : Implement IDisposable on 'B' because it creates members of the following IDisposable types: 'A'.

要解决此警告,我必须将此代码添加到类 B:

    ~B()  { delete m_a; }

但是我不明白为什么。 A 类通过其析构函数(和终结器)实现 IDisposable。
因此,每当 A 被垃圾回收时,肯定会调用 A 的终结器或析构函数,从而释放其非托管资源。

为什么 B 必须添加一个析构函数来调用其 A 成员的“删除”?
如果 B 显式调用“delete m_a”,GC 是否只会调用 A 的析构函数?


编辑:如果您使用声明 A 成员的“语法糖”方法,这似乎会自动工作,如下所示:

ref class B
{
public:
B() { }
protected:
A m_a;
};

但这并不总是可能的。

为什么 GC 不够聪明,无法在没有其他指针指向它时自动处理 A^ 的托管引用指针?

最佳答案

您应该为成员使用堆栈语义,并向包含类添加析构函数。然后该成员将被处置。参见 http://msdn.microsoft.com/en-us/library/ms177197.aspx

ref class B
{
public:
B() {}
~B() {}
protected:
A m_a;
};

成员仍然是裁判。类型并且仍然在堆上创建。

编辑:

.net 中的 Dispose 充其量是不幸的,在 C# 中,整个确定性行为被破坏,您必须非常严格地调用 Dispose 才能获得大多数 c++ 开发人员期望的行为。

在 c++/cli 中,堆栈语义使其变得更好。如果您不能使用它们,您将不得不显式调用 dispose,这在 c++/cli 中由析构函数表示。

如果成员像 C# 一样是普通托管指针,则自动将处置调用链接到成员的唯一方法是通过堆栈语义,您必须手动链接调用。

许多类可能持有相同的 A^ 指针,没有办法知道哪个应该调用析构函数。

您收到警告是因为您已经实现了导致您的类实现 IDispose 的析构函数。这使您有机会以确定性方式进行清理。

单独的GC只能收集一个没有引用的对象并调用finalizer。这远非确定性的。请注意,依靠终结器进行清理应该只是一个安全网,因为它可能会在未来很长一段时间内被调用(如果有的话)。

我建议尝试设计您的代码以允许上述模式。

关于garbage-collection - 为什么 GC 不会自动处理我类(class)的成员?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1265990/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com