Подтвердить что ты не робот

Альтернатива boost:: shared_ptr во встроенной среде

Я использую С++ во встроенной среде linux, которая имеет GCC version 2.95.

Я просто не могу извлечь файлы boost::shared_ptr с bcp, это слишком тяжело.

Мне бы хотелось, чтобы это была простая реализация интеллектуального указателя boost::shared_ptr, но без всех накладных расходов boost (если это возможно...).

Я мог бы придумать свой собственный источник повышения скорости чтения, но я боюсь пропустить одну или несколько точек, кажется, легко сделать ошибочный смарт-указатель, и я не могу позволить себе иметь ошибку.

Итак, существует ли "простой" пример реализации или реализации boost::shared_ptr (или любой эквивалентный интеллектуальный указатель ссылок), который я мог бы использовать или что я мог бы принять за вдохновение?

4b9b3361

Ответ 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 обрабатывают его довольно хорошо, поэтому вы сами здесь.