Управление указателем с помощью синглтона во время строительства?

Я хобби с ++ программист, и это мой первый пост.

Прежде всего, позвольте мне сказать вам, что я работаю над кроссплатформенным ANSI C ++.

Я только что проделал большую работу, выясняя, как управлять памятью, и, наконец, я научился использовать std :: vector и управлять моими указателями вручную во время удаления.

Кроме того, я использовал boost :: smart_ptr, и он наконец-то нажал.

Однако я только что наткнулся на некоторый код, где у нас будет класс Foo, конструктор которого регистрируется в FooManager (A singleton)

Foo::Foo()
{
FooManager::Instance()->register(this);
}

Во время уничтожения FooManager, он перебирает std :: vector и применяет стирание и удаление к каждому элементу, эффективно очищая память Foo.

FooManager::~FooManager()
{
// iterate over the container of Foo pointers
// erase the pointer from container and delete the pointer
}

Я был сбит с толку, потому что мы не а) используем boost :: smart_ptr, чтобы обернуть указатель во время создания, и б) мы используем приемы управления памятью в конструкторах и деструкторах.

Это жизнеспособное решение или существуют страшные опасности, связанные с использованием деструктора синглтона для очистки объектов, которыми он управляет?

Из моих собственных испытаний я обнаружил один фундаментальный недостаток. Foo НЕ ДОЛЖЕН размещаться в стеке. Объект разыменовывает себя, когда выходит из области видимости. Когда вызывается деструктор FooManager, он пытается удалить его снова. Это генерирует ошибку подтверждения:

_ASSERTE (_BLOCK_TYPE_IS_VALID (pHead-> nBlockUse));

Это единственный недостаток? Должен ли я перенести регистрацию с менеджером за пределы конструктора Foo? Должен ли я иметь отдельную функцию FooManager, которая очищает память, которую я вызываю вручную в конце срока службы моей программы? Что вы думаете по этому поводу?

2

Решение

Я вижу пару проблем:

  1. Одиночный экземпляр FooMananger является статической переменной и имеет срок жизни от начала до конца программы. если мы удаляем только Foo из деструктора FooManager, который может быть вызван только в конце программы, то мы вообще не делаем никакого управления памятью. это равносильно тому, что вы никогда не удаляете экземпляры Foo. не так ли?

  2. Как вы уже выяснили, способ регистрации FooManager указатель внутри конструктора Foo делает невозможным размещение объектов Foo в стеке. в итоге вы получите указатель, указывающий на недопустимое место в памяти или на место, к которому вы не должны прикасаться.

Обычной практикой является использование умных указателей, в зависимости от ваших потребностей, вы можете использовать boost :: shared_ptr или boost :: scoped_ptr, std :: uniqe_ptr (c ++ 11) и т. Д.

0

Другие решения

Тангенциально, я думаю, что дизайн ваших классов немного асимметричен:

  1. все объекты Foo регистрируются во время создания;
  2. FooManager сбрасывает все регистрации а также удаляет все зарегистрированные объекты Foo при его удалении.

Проблема в том, что FooManager просто агрегирует объекты Foo или обрабатывает их жизненный цикл?

  • Если FooManager предоставляет агрегацию только для объектов Foo, то он не должен удалять их при уничтожении, поскольку он не «владеет» ими; должно быть достаточно простой внутренней отмены регистрации (примечание: могут быть проблемы в многопоточных программах).

  • Если FooManager должен иметь более жесткий контроль над объектами Foo (т.е. обрабатывать весь их жизненный цикл), Фабричный образец может быть более подходящим: только FooManager может выделять объекты Foo.

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector