Nano Hash - криптовалюты, майнинг, программирование

повысить shared_ptr: разница между оператором = и сбросом?

Есть ли различия между двумя фрагментами кода ниже? Является ли какой-либо из них предпочтительнее другого?

оператор=

boost::shared_ptr<Blah> foo; // foo.ptr should be NULL
foo = boost::shared_ptr<Blah>(new Blah()); // Involves creation and copy of a shared_ptr?

сбросить

boost::shared_ptr<Blah> foo; // foo.ptr should be NULL
foo.reset(new Blah()); // foo.ptr should point now to a new Blah object

Примечание. Мне нужно определить shared_ptr, а затем установить его в другой строке, потому что я использую его в фрагменте кода, например:

boost::shared_ptr<Blah> foo;
try
{
  foo.reset...
}
foo...
18.03.2011


Ответы:


1

operator= присваивает shared_ptr shared_ptr, а reset заставляет shared_ptr владеть указателем. Итак, в основном нет никакой разницы между примерами, которые вы опубликовали. Тем не менее, вы не должны отдавать предпочтение ни одному из них и просто использовать make_shared:

foo = boost::make_shared<Blah>();

Кроме того, если возможно, вы можете избежать объявления shared_ptr без инициализации, заключив блок try-catch в отдельную функцию, которая просто возвращает shared_ptr во вновь созданный объект:

boost::shared_ptr<Blah> createBlah() {
    try {
        // do stuff
        return newBlah;
    }
    catch ...
}
18.03.2011
  • Не могли бы вы обосновать свой комментарий о том, что make_shared следует предпочесть? 15.03.2013
  • Создание объекта с использованием new и инициализация с его помощью shared_ptr — это двухэтапный процесс. Теоретически создание объекта может завершиться успешно, но инициализация shared_ptr может завершиться неудачно, и в этом случае произойдет утечка памяти, если вы явно не обработаете этот случай. make_shared позаботится об этом за вас. Согласно документации, это также быстрее. 15.03.2013

  • 2

    operator= принимает еще один shared_ptr в качестве параметра, тем самым создавая еще одну копию (и увеличивая счетчик ссылок), в то время как reset() принимает указатель и, возможно, средство удаления, таким образом, на самом деле создавая новый shared_ptr поверх текущего.

    reset эквивалентен (и, вероятно, реализован как)

    void reset(T p, D d)
    {
       shared_ptr shared(p,d);
       swap( shared );
    }
    

    operator=, вероятно, будет реализован как:

    shared_ptr& operator=( shared_ptr const& other )
    {
       shared_ptr shared(other);
       swap(other);
       return *this;
    }
    

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

    18.03.2011
  • reset также перегружен для получения другого общего указателя, и в этом случае он эквивалентен присваиванию. 18.03.2011
  • CashCow: не могли бы вы объяснить роль строки shared_ptr shared(other); в вашей реализации operator=? 07.06.2013

  • 3

    foo.reset(p) определяется как эквивалент shared_ptr(p).swap(foo).

    Назначение логически эквивалентно копированию и обмену и, возможно, реализовано таким образом. Итак, foo = shared_ptr(p); эквивалентно foo.swap(shared_ptr(p)). Возможно, с дополнительной копией, если у компилятора очень плохой день.

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

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

    18.03.2011

    4

    Оператор присваивания создает новый общий объект из существующего, увеличивая счетчик ссылок

    CSharedObj& CSharedObj::operator=(CSharedObj& r) noexcept
    { 
         if(*this != r){
            //detach from the previous ownership
            if(0 == dec()) delete m_pControlObj;
            //attach to the new control object and increment the reference count
            r.inc();
            m_pControlObj = r.m_pControlObj;
        }
        return *this;
    }
    

    в то время как вызов сброса не создает новый общий объект, а скорее новое право собственности - присоединение к новому базовому указателю (через объект управления)

    void CSharedObj::reset(Ptr pointee) noexcept
    {
       //check if this is a last reference-detach from the previous ownership
       if(0==dec()) delete m_pControlObj;
       // create the ownership over the new pointee (refCnt = 1)
       m_pControlObj = new (std::nothrow) CControlObj(pointee);
    }
    
    13.09.2017
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..