boost shared_ptr: разница между оператором = и сбросом? - PullRequest
11 голосов
/ 18 марта 2011

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

оператор =

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?

1010 * Сброс *

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...

Ответы [ 4 ]

15 голосов
/ 18 марта 2011

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 ...
}
3 голосов
/ 18 марта 2011

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

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

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;
}

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

2 голосов
/ 18 марта 2011

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

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

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

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

0 голосов
/ 13 сентября 2017

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

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);
}
...