Когда сделать объект удалить себя? - PullRequest
3 голосов
/ 19 июня 2009
Callback* p = new Callback;
function(p);

Если я хочу удалить объект обратного вызова, когда и как это удалить?

Если он будет удален досрочно, обратный вызов может завершиться ошибкой сегментации.

Ответы [ 6 ]

17 голосов
/ 19 июня 2009

Лучшее решение для этого - использовать умный указатель.
Вы инициализируете указатель обратным вызовом и передаете его функции. когда функция или какой-либо другой процесс выполняется, обратный вызов будет автоматически удален интеллектуальным указателем.
Хорошая реализация умного указателя: boost::shared_ptr<>

3 голосов
/ 19 июня 2009

Если код настолько же тривиален, как и вы, то есть после выполнения функции func () имеется только одна ссылка на указатель обратного вызова, я думаю, что auto_ptr будет достаточно:

std::auto_ptr<Callback> p(new Callback);
func(p.get());

Это также гарантирует, что если func () сгенерирует исключение, память все равно будет освобождена.

1 голос
/ 19 июня 2009

Если ваш код такой же простой, как и то, что вы написали, и func() напрямую вызывает обратный вызов в какой-то момент, то этого должно быть достаточно:

Callback p;
func(&p);

Однако, если func() сохраняет ссылку или указатель на обратный вызов в другом месте, вам необходимо отслеживать время жизни этой ссылки.

1 голос
/ 19 июня 2009

Предполагая, что func () является единственной функцией, использующей этот конкретный объект Callback, и что этот код всегда выполняется в порядке, в котором создается объект Callback, я бы поставил его после вызова func (). Таким образом, если вам нужно отредактировать func (), вам не нужно беспокоиться о том, где объект Callback удаляется. Это также гарантирует, что все указатели были очищены, так как указатель func () должен был прекратить существовать после завершения функции, единственное, что осталось сделать, это удалить указатель, оставленный ссылкой на него.

Я прошу прощения, если мое понимание указателей в C ++ неверно и заставило меня дать неправильный ответ, я всегда был немного смущен этим.

1 голос
/ 19 июня 2009

Вы можете иметь счетчик приращения / уменьшения при использовании обратного вызова. Когда он используется, увеличивайте счетчик, когда он больше не используется, уменьшайте его. Когда он достигнет 0 или -1, освободите его.

0 голосов
/ 19 июня 2009

Объект «вызывающий-backer», содержащий обратный вызов (тот, кто выполняет обратные вызовы к нему), может быть надлежащим владельцем (определяющим время жизни обратного вызова и, в частности, использующим delete, чтобы покончить с объектом обратного вызова , удерживая его с auto_ptr и т. д.) тогда и только тогда, когда его семантика такова, что он позволяет определить, когда больше не понадобятся никакие обратные вызовы - это невозможно отличить по такой скудной информации, которая представлена ​​в вопросе.

Вам также могут понадобиться способы для кода, который создает обратный вызов (и передает владение им вызывающей стороне), чтобы явно попросить "вызывающую вызывающую сторону" удалить объект обратного вызова (и выполнить больше никаких обратных вызовов), когда указанный код определяет, что больше никаких обратных вызовов больше не потребуется.

В других ответах упоминаются более умные указатели, чем auto_ptr, чтобы заставить проблемы исчезать из-за того, «кому это принадлежит» (буст shared_ptr, подсчет ссылок, свернутый вручную, ...) - это может быть хорошо, если вас заставляют использовать C ++ по другим причинам, но на самом деле тоскливо по языку со сборщиком мусора, но, если вы выберете C ++ именно потому, что он дает вам полный контроль над использованием памяти, то правильное определение владения объектом и проблем времени жизни не является обязательным (и это может серьезно оптимизировать использование ресурсов по сравнению с любым более или менее автоматизированным «сборщиком мусора» - это важно только тогда, когда вам нужно , конечно же, нужно тщательно контролировать использование ресурсов; -).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...