Альтернатива boost:: shared_ptr во встроенной среде
Я использую С++ во встроенной среде linux, которая имеет GCC version 2.95
.
Я просто не могу извлечь файлы boost::shared_ptr
с bcp, это слишком тяжело.
Мне бы хотелось, чтобы это была простая реализация интеллектуального указателя boost::shared_ptr
, но без всех накладных расходов boost
(если это возможно...).
Я мог бы придумать свой собственный источник повышения скорости чтения, но я боюсь пропустить одну или несколько точек, кажется, легко сделать ошибочный смарт-указатель, и я не могу позволить себе иметь ошибку.
Итак, существует ли "простой" пример реализации или реализации boost::shared_ptr
(или любой эквивалентный интеллектуальный указатель ссылок), который я мог бы использовать или что я мог бы принять за вдохновение?
Ответы
Ответ 1
если вам не нужно смешивать общий и слабый ptr, и вам не нужны удаленные кустомы, вы можете просто использовать быстрый и грязный my_shared_ptr:
template<class T>
class my_shared_ptr
{
template<class U>
friend class my_shared_ptr;
public:
my_shared_ptr() :p(), c() {}
explicit my_shared_ptr(T* s) :p(s), c(new unsigned(1)) {}
my_shared_ptr(const my_shared_ptr& s) :p(s.p), c(s.c) { if(c) ++*c; }
my_shared_ptr& operator=(const my_shared_ptr& s)
{ if(this!=&s) { clear(); p=s.p; c=s.c; if(c) ++*c; } return *this; }
template<class U>
my_shared_ptr(const my_shared_ptr<U>& s) :p(s.p), c(s.c) { if(c) ++*c; }
~my_shared_ptr() { clear(); }
void clear()
{
if(c)
{
if(*c==1) delete p;
if(!--*c) delete c;
}
c=0; p=0;
}
T* get() const { return (c)? p: 0; }
T* operator->() const { return get(); }
T& operator*() const { return *get(); }
private:
T* p;
unsigned* c;
}
Для всех, кто интересуется make_my_shared<X>
, его можно тривиально реализовать как
template<class T, class... U>
auto make_my_shared(U&&... u)
{
return my_shared_ptr<T>(new T{std::forward<U>(u)...});
}
называемый
auto pt = make_my_shared<T>( ... );
Ответ 2
Существует также std:: tr1:: shared_ptr, который является стандартным лифтом С++ 11 от boost. Вы можете выбрать это, если это разрешено, или написать свой собственный с подсчетом ссылок.
Ответ 3
Какие "форсированные накладные расходы" вас беспокоят, и каким образом shared_ptr
"слишком тяжелый" для вашего приложения? Накладные расходы просто не используются при использовании Boost (по крайней мере, если вы используете только библиотеки только для заголовков, такие как библиотека интеллектуальных указателей); единственные накладные расходы, которые я могу придумать относительно shared_ptr
, следующие:
- Сопоставление ссылок на потоки; поскольку вы используете древний компилятор, я предполагаю, что у вас также есть старая библиотека времени и ядро, поэтому это может быть очень неэффективно. Если ваше приложение однопоточно, вы можете отключить его с помощью #defining
BOOST_DISABLE_THREADS
.
- Распределение структуры подсчета ссылок вместе с управляемым объектом. Вы можете исключить дополнительное выделение, создав объект с помощью
make_shared()
или allocate_shared()
.
Во многих случаях вы можете исключить накладные расходы из критически важного кода, не создавая объектов или копируя общие указатели - указатели прохода по ссылке и только копируете их, когда вам действительно нужно.
Если вам нужна безопасность потоков для некоторых указателей, но не для других, и (после профилирования и удаления всех ненужных распределений и копирования указателей) вы обнаружите, что использование общих указателей по-прежнему вызывает значительные накладные расходы, тогда вы можете рассмотреть возможность использования intrusive_ptr
и управлять собственным подсчетом ссылок внутри объекта.
Также может быть полезно обновить до современной версии GNU/Linux, если это возможно. Синхронизация потоков намного эффективнее с момента введения futexes в Linux 2.6. Вы можете обнаружить, что это помогает и другим образом; за последнее десятилетие было много улучшений. Более современный компилятор также предоставит стандартный (TR1 или С++ 11) общий указатель, поэтому вам не понадобится Boost для этого.
Ответ 4
Я предлагаю вам использовать shared_ptr отдельно. Однако, если вы ищете простую реализацию
- с некоторыми модульными тестами
- небезопасный поток
-
базовая поддержка полиморфного назначения < - сообщите мне, если вы заинтересованы
- пользовательские удалители (например, дескрипторы массива или пользовательские функции для специальных ресурсов)
Посмотрите здесь: Создание безопасного потока, не связанного с потоком
Ответ 5
Вы можете использовать shared_ptr
без накладных расходов Boost: это реализация только для заголовка. Если вы не используете какие-либо другие классы, будет скомпилирован только shared_ptr
.
Реализация shared_ptr
уже довольно скудная, но если вы хотите избежать промежуточного блока подсчета ссылок и (потенциального) виртуального вызова для функции deleter, вместо этого вы можете использовать boost::intrusive_ptr
, что больше подходит для встроенных среды: он работает на счетчике ссылок, встроенном в сам объект, вам просто нужно предоставить несколько функций, чтобы увеличить/уменьшить его. Недостатком является то, что вы не сможете использовать weak_ptr
.
Я не могу прокомментировать, насколько gcc 2.95 встраивал/сворачивал экземпляры шаблонов (это очень старый компилятор), более поздние версии gcc обрабатывают его довольно хорошо, поэтому вы сами здесь.