Управление необработанными указателями в C ++ - PullRequest
1 голос
/ 23 ноября 2010

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

Спасибо.

Ответы [ 4 ]

5 голосов
/ 23 ноября 2010

Вы просите невозможного - с одной стороны, вы запрашиваете исключительную производительность, такую, которую умные указатели, как вы заявляете, не могут предоставить, и вы также просите безопасности и аккуратности. Ну, один идет за счет другого, на самом деле. Конечно, вы могли бы попытаться написать собственный разделяемый указатель, который был бы более легким, чем Boost, но все же предоставлял бы базовую функциональность. Кстати, вы на самом деле пробовали boost :: shared_ptr? Это на самом деле замедлило производительность?

1 голос
/ 23 ноября 2010

Ваш вопрос очень неловкий: вы спрашиваете о производительности с грязной логикой?

shared_ptr действительно невероятная производительность, и, хотя вы можете стать лучше, это, вероятно, ваш лучший выбор: он работает.

Вы можете найти другой интеллектуальный указатель Boost: boost :: intrusive_ptr .

Это делается за счет вышесказанного: weak_ptr и взамен позволяет иметь одно выделение памяти как для счетчика, так и для объекта. Сочетание этих двух дает небольшое увеличение производительности.

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

0 голосов
/ 23 ноября 2010

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

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

Другой вариант - использовать интеллектуальный указатель, который обеспечиваетдоступ к базовому указателю.Если вы пытаетесь избежать чрезмерной нагрузки на перегруженный operator->, то, возможно, стоит попробовать.Сохраняйте умные указатели в списках (это делает управление временем жизни для вас), а затем при работе с объектами вы можете получить необработанный указатель для каждого из них и работать с ним (таким образом, вы не несете издержек при перегрузке operator->так далее.).Например:

std::vector<smart_ptr<T> > objects;

if(!objects.empty()) {
    smart_ptr<T> *objects_raw=&objects[0];
    for(size_t n=objects.size(),i=0;i<n;++i) {
        T *object=objects_raw[i].get_ptr();

        // do stuff
    }
}

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

0 голосов
/ 23 ноября 2010

Интрузивные умные указатели, как правило, более эффективны, чем обычные умные указатели, но проще, чем тупые указатели. Например, проверьте boost::intrusive_ptr<T>

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