Когда я создаю следующий код C++/CLI в VS2008, отображается предупреждение об анализе кода 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;
};
предупреждение: CA1001: Microsoft.Design: Реализуйте IDisposable для «B», поскольку он создает члены следующих типов IDisposable: «A».
Чтобы устранить это предупреждение, мне пришлось бы добавить этот код в класс B:
~B() { delete m_a; }
Но я не понимаю, почему. Класс A реализует IDisposable через свой деструктор (и финализатор).
Таким образом, всякий раз, когда A подвергается сборке мусора, вызывается финализатор или деструктор A, освобождая его неуправляемые ресурсы.
Почему B должен добавлять деструктор, чтобы вызвать 'delete' для своего члена A?
Будет ли сборщик мусора вызывать деструктор A только в том случае, если B явно вызывает "delete m_a"?
Изменить: похоже, это работает автоматически, если вы используете метод "синтаксического сахара" для объявления члена A, например:
ref class B
{
public:
B() { }
protected:
A m_a;
};
но это не всегда возможно.
Почему GC не достаточно умен, чтобы автоматически избавиться от управляемого указателя ссылки A^, если ни у кого больше нет указателя на него?