Удаление из станд. STL:: очередь, не разрушая удаленный объект?

Заключительный размер исполняемого файла на диске в основном не важен в эти дни. Ваша программа может загрузить несколько миллисекунд быстрее, но как только она начинает работать, различие неразличимо.

Некоторые люди могут больше с подозрением относиться к Вашему исполняемому файлу просто, потому что он сжат с UPX. В зависимости от Ваших конечных пользователей это может или не может быть важным соображением.

7
задан MSalters 5 October 2009 в 10:29
поделиться

5 ответов

Если вы поместите указатели на объекты в очереди (и в любой другой контейнер STL), указатели не будут удалены при их удалении.

Для пояснения: при использовании std: : queue и удалить объект, вызываемый деструктором some_obj *. Но деструктор для простого указателя (или любого типа POD - int, char и т. Д.) Пуст, не работает. Тонкая грань здесь в том, что деструктор для some_obj * очень отличается от деструктора для some_obj.

17
ответ дан 6 December 2019 в 05:43
поделиться

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

Если вы использовали контейнер прокси-типа , как необработанные указатели, интеллектуальные указатели (shared_ptr, weak_ptr) или адаптеры (как boost :: reference_wrapper), тогда контейнер STL уничтожит прокси, но не тип. Выбор одного из них обычно зависит от того, как вы хотите распоряжаться ресурсами.

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

Современное использование движется в сторону подхода shared_ptr, так как он устраняет проблему владения. Гарантируется, что объект будет живым, когда вы извлечете его из контейнера, и если никто другой не имеет shared_ptr, объект будет автоматически удален, когда локальный shared_ptr выйдет за пределы области видимости. Использование weak_ptr сохранит право собственности на исходный код, но позволит вам проверить действительность указателя (если он был удален) перед использованием. Это может позволить вам избежать выполнения операции над объектом, который будет сразу же удален.

Проблема с подходом shared_ptr / weak_ptr состоит в том, что он заставляет вас использовать shared_ptr для хранения исходного ресурса. Это означает, что вы не сможете поместить указатель в подобъект (атрибут-член) другого класса без перепроектирования класса для хранения атрибута через shared_ptr, и это будет иметь другие последствия (атрибуты больше не будут смежными в памяти , потребуется больше операций динамического распределения ...)

Метод, который вряд ли можно увидеть, - это использование адаптеров как boost :: reference_wrapper <>. Оболочка ссылок - это прокси-объект, который содержит ссылку на исходный объект и сам копируемый. Преимущество перед простыми необработанными указателями заключается в том, что при чтении кода становится ясно, что управление ресурсом осуществляется вне очереди: код, извлекающий данные из очереди, не должен удалять объект. Преимущество перед подходом интеллектуального указателя заключается в том, что вам не нужно перепроектировать другие части вашей системы для использования интеллектуальных указателей. Недостатком является то, что, как и в подходе с необработанным указателем, вы должны убедиться, что время жизни указанного объекта превышает срок действия ссылки в контейнере вручную.

7
ответ дан 6 December 2019 в 05:43
поделиться
class someobj_t {};

std::queue<someobj_t> q;
...

someobj_t ppd = q.front(); // ppd is not a reference
q.pop();

// ppd now contain removed object

Если вы не хотите, чтобы someobj_t копировался, вы можете использовать std :: queue > .

4
ответ дан 6 December 2019 в 05:43
поделиться

Как насчет использования списка указателей на объекты?

3
ответ дан 6 December 2019 в 05:43
поделиться

Подумайте о том, что элементы в контейнере находятся "в области видимости" этого контейнера, когда элемент удаляется из контейнера, это похоже на выход из области видимости функции. Если переменная является указателем, при выходе из области действия с элементом ничего не происходит. Если переменная является локальной в стеке, деструктор будет автоматически вызван при выходе из области видимости.

Сохранение указателей в контейнерах имеет те же недостатки, что и выделение в локальный необработанный указатель, память не очищается автоматически. В функции, если вы не удалите указатель или не передадите владение, вернув его, вы получите утечку памяти.

При хранении необработанных указателей в контейнере владение может стать немного неоднозначным, и легко могут произойти утечки. Взгляните на tr1 :: shared_ptr и сохраните их в контейнерах.

std ::

2
ответ дан 6 December 2019 в 05:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: