Слабый / общий указатель, определить, когда остается один пользователь, повысить - PullRequest
0 голосов
/ 25 сентября 2011

Мне нужен указатель, где я могу сказать, когда счетчик ссылок равен единице. По сути, указатель работает как слабый_птр, но очистка должна выполняться вручную. То есть программа очень часто проходит цикл своих указателей и проверяет, у каких из них осталась только одна ссылка. Некоторых он будет чистить, других он будет сохранять еще дольше (на случай, если кому-то это понадобится снова).

Теперь я знаю, как это сделать, используя комбинацию пользовательской функции очистки и weak_ptr. Я просто думаю, что то же самое можно сделать с помощью более простого кода, если бы я мог просто выяснить, когда остается только один пользователь shared_ptr.

Я знаю, что shared_ptr имеет функцию use_count, но в документации есть зловещее примечание: "... не обязательно эффективно. Используйте только для целей отладки и тестирования ..." Естественно Я не очень хочу использовать что-то с таким предупреждением. В любом случае мне не нужен счетчик, просто способ определить, когда остался только один.

Есть ли какая-нибудь бустер-оболочка, которая достигает того, что я хочу (может быть в любой библиотеке)? Или я должен использовать технику, которую я уже знаю, о пользовательской функции очистки в сочетании со слабым_птром?

Ответы [ 3 ]

2 голосов
/ 25 сентября 2011

Как правило, вы не можете точно определить количество ссылок. Но вы можете сказать, когда он ровно один - используйте unique().

1 голос
/ 25 сентября 2011

Деструктивно преобразует ваши shared_ptr с в weak_ptr с, а затем обратно shared_ptr с, за исключением того, что некоторые из них будут нулевыми. Конечно, нельзя сказать, как это влияет на производительность, но, учитывая интерфейс, который у нас есть, это либо то, либо use_count.

Может выглядеть так:

std::for_each(begin, end, [](element_type& pointer)
{
    std::weak_ptr<element_type::element_type> weak = element_type(std::move(pointer));
    pointer = weak.lock();
});
auto predicate = [](element_type& pointer) { return !pointer; };
container.erase(std::remove_if(begin, end, predicate), end);
0 голосов
/ 25 сентября 2011

Когда вы делаете что-то сложное, что не может быть полностью представлено обычной системой shared_ptr, вы можете рассмотреть возможность использования intrusive_ptr вместо этого - ваша реализация intrusive_ptr_release может затем ставить объекты в очередьдля последующего уничтожения вместо того, чтобы удалить их немедленно.Обратите внимание, что intrusive_ptr нельзя напрямую использовать с weak_ptr, хотя вы можете создать свой собственный вариант weak_ptr, если хотите.Имейте в виду, однако, что если вы используете несколько потоков, подсчет ссылок может стать немного сложным.

Если вы не можете использовать навязчивый указатель, и допустимо аннулировать существующие weak_ptr s, когдапоследний shared_ptr потерян, вы можете иметь деструктор для shared_ptr, поместив указатель raw обратно в ваш кеш (или любой другой), помеченный для возможной очистки.Вы можете перемотать его в shared_ptr при следующем получении.Однако, опять же, у этого есть обратная сторона: потерять все weak_ptr с объектом в момент псевдо-разрушения.

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

...