Хранить слабый указатель на себя

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

class MyClass {
    //...
    boost::weak_ptr<MyClass> m_self;
    //...
};

boost::shared_ptr<MyClass>
Factory::Factory::Factory::CreateMyClass() {
    boost::shared_ptr<MyClass> obj(new MyClass(...));
    boost::weak_ptr<MyClass> p(obj);
    obj->storeSelfPointer(p);
    return obj;
}

Затем класс переходит к использованию m_self, блокируя его и передавая результирующий общий указатель.

В моей жизни я не могу понять, что она пыталась выполнить. Есть ли какой-то образец или идея, которые объясняли бы эту реализацию? Мне кажется, что это совершенно бессмысленно, и я бы хотел его реорганизовать.

EDIT. Я должен отметить, что ни одно из мест, которые используют полученный интеллектуальный указатель, полученный из блокировки m_self, фактически сохраняет умный указатель.

Ответы

Ответ 1

Возможное использование этой "конструкции" может заключаться в использовании m_self.lock() для генерации общих указателей из этого.

Если вы удалите этот слабый указательный элемент, удержание отсчета ссылок сгенерированным общим указателем из this будет неверным.

Он достигает того же, что std::enable_shared_from_this, что интересно, cppreference.com упоминает этот проект:

Общая реализация для enable_shared_from_this заключается в том, чтобы удерживать слабый ссылку (например, std:: weak_ptr). Конструкторы std:: shared_ptr обнаруживает наличие свойства enable_shared_from_this и назначить вновь созданный std:: shared_ptr внутренне сохраненным слабая ссылка

И стандарт С++, раздел § 20.8.2.4 10, упоминает ту же возможную реализацию:

Конструкторы shared_ptr, которые создают уникальные указатели, могут наличие базы enable_shared_- from_this и присвоить новую создал shared_ptr для своего Участник __weak_this


Возможный рефакторинг:

  • Если вы используете С++ 11, вы можете удалить член std::weak_ptr и публично наследовать от std::enable_shared_from_this<T>. Вы должны получить общий указатель из этого, вызвав shared_from_this().

  • Если вы не используете С++ 11, но можете использовать boost, используйте boost::enable_shared_from_this, см. дополнительную документацию. Вы должны получить общий указатель из этого, вызвав shared_from_this().

  • Если вы не используете С++ 11 и не можете использовать boost, вы можете привести предлагаемую реализацию стандарта к вашей базе кода, он достаточно короткий:

Код: (скопирован из § 20.8.2.4 - 11, удалите ведущие подчеркивания, и вы, вероятно, захотите переименовать его)

template<class T> class enable_shared_from_this {
    private:
     weak_ptr<T> __weak_this;
    protected:
     constexpr enable_shared_from_this() : __weak_this() { }
     enable_shared_from_this(enable_shared_from_this const &) { }
     enable_shared_from_this& operator=(enable_shared_from_this const &) { return *this; }
     ~enable_shared_from_this() { }
    public:
     shared_ptr<T> shared_from_this() { return shared_ptr<T>(__weak_this); }
     shared_ptr<T const> shared_from_this() const { return shared_ptr<T const>(__weak_this); }
};

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