Мягкие (не слабые) ссылки в C ++ - возможно ли это? Есть ли реализация? - PullRequest
6 голосов
/ 04 июля 2010

В C ++ я использую boost::shared_ptr и boost::weak_ptr для автоматического удаления ненужных объектов. Я знаю эти работы с подсчетом ссылок.

В Java память управляется сборщиком мусора, который рассматривает встроенные ссылки на объекты как strong , WeakReference как слабый и SoftReference как нечто промежуточное (может быть собрано GC, но может также выжить в GC), что действительно удобно для кэширования объектов в течение некоторого времени, но выбрасывает их, как только объем свободной памяти уменьшается.

Так что теперь я вернулся в C ++, и мне не хватает комфорта, когда есть мягкие ссылки. Интересно, возможна ли мягкая ссылка с подсчетом ссылок вообще? Когда последняя сильная ссылка на объект очищается и остается мягкая ссылка, когда она все-таки будет удалена? Я мог бы подумать о некоторых схемах, но ни одна из них не кажется мне умной.

На всякий случай, если есть правильная семантика для мягких ссылок наряду с подсчетом ссылок, мне интересно, реализовано ли это уже, возможно, способом, который даже совместим с boost::shared_ptr (или эквивалентом C ++ TR1 std::shared_ptr в этом отношении ).

Если ответ на оба вопроса отрицательный, каковы альтернативы в сценарии кэширования объектов?

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

Ответы [ 5 ]

7 голосов
/ 04 июля 2010

Как отмечали другие, вы можете найти ссылочных подсчитанных указателей (и их сопровождающих слабых аналогов ) в библиотеке Boost, но чего нет в soft reference Идея - это некоторое понимание ограничений памяти среды выполнения. Например, в Java SoftReference существенно не отличается от WeakReference в своих возможностях; скорее это контракт на то, как среда выполнения сохранит или изгонит два вида ссылок перед лицом разницы в памяти.

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

2 голосов
/ 05 июля 2010

Если вы действительно хотите повторить это поведение, вы можете использовать сборщик мусора (например: http://www.hpl.hp.com/personal/Hans_Boehm/gc/) и использовать его для заботы о вашем объекте или его подмножестве, где было бы полезно использование SoftReferences.

Но я бы предпочел пойти на решение, более родное для C ++, чем репликация поведения Java - но ничто не мешает вам сделать это.

1 голос
/ 04 июля 2010

Вы можете реализовать свой собственный кэш LRU и новый smart_pointer, связанный с таким кешем.Я не думаю, что такая структура существует в Boost или стандартном C ++ (во всяком случае, вне головы).Если вы делаете веб-приложение или что-то ... вы можете использовать libmemcached, который является C-интерфейсом для memcached.

Мне трудно представить себе ситуацию, когда такой объект будет так дорого создавать./ уничтожить ... в то время как было бы дешево повторно инициализировать ... что кэш LRU станет полезным.Но если он вам действительно нужен, у вас есть инструменты для его создания.

0 голосов
/ 27 сентября 2011

Вы можете переместить данные с мягкой ссылкой вне приложения в ОС, используя что-то вроде buffcacher .

Я не знаю ни одной библиотеки, предлагающей это, я только когда-либо катал свою собственную.

Это настолько быстро и справедливо, что становится полезным кэшировать проверку «безопасных файлов cookie» на веб-серверах и выполнять другие задачи, которые кажутся почти небольшими для обычного кэша.

0 голосов
/ 04 июля 2010

Нет, такого нет в C ++.И не должно быть.Каждый объект служит важной цели.Если это не так, почему у вас все еще есть?Хранение объектов таким образом - утечка памяти.Если вам нужен объект, он вам нужен.Если нет, уничтожь его.Между полезным и бесполезным нет никакого промежутка, либо он служит цели, либо нет.

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

Редактировать: В объектном кэшировании люди обычно используют LRU-кэши.Когда вы пропускаете кеш, ссылка на наименее использованный объект уничтожается (если кеш заполнен), новый объект создается и помещается как последний использованный, а все остальные перемещаются вниз.Однако, как правило, вам нужно извлечь элементы с диска, прежде чем вам действительно понадобится стратегия кэширования в C ++.Стоимость создания большинства объектов просто невелика.

...