2010-11-23 3 views
1

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

Спасибо.

+7

Попробуйте умный указатель. Профиль, чтобы проверить, имеет ли он слишком большое влияние. Скорее всего, это будет не слишком много, и это, вероятно, будет меньше, чем большинство решений для вашего собственного решения. – sje397 2010-11-23 10:25:33

+1

К сожалению, вы не можете многое сделать. Вам необходимо определить обязанности, то есть кто несет ответственность за владение вашими ресурсами. Это, на мой взгляд, фундаментальная проблема с C++ и, вероятно, одна из самых больших причин, по которой люди переходят на другие языки. – 2010-11-23 10:27:49

+1

Вы * профилировали * умный указатель или это только ваша догадка? – Simone 2010-11-23 10:28:27

ответ

5

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

+2

Один вопрос о `shared_ptr`: лучше использовать` make_shared` для его создания, он намного эффективнее. – 2010-11-23 10:32:23

1

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

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

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

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

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

0

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

0

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

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

Другим вариантом является использование интеллектуального указателя, обеспечивающего доступ к основному указателю. Если вы пытаетесь избежать накладных расходов, вызвав перегруженный 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 
    } 
} 

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

Смежные вопросы