shared_from_this называют от конструктора

Я должен зарегистрировать объект в контейнере после его создания. Без интеллектуальных указателей я использовал бы что-то вроде этого:

a_class::a_class()
{
    register_somewhere(this);
}

С интеллектуальными указателями я должен использовать shared_from_this но я не могу использовать это в конструкторе.

Существует ли очевидный способ для решения этой проблемы? Что Вы сделали бы в аналогичной ситуации? Я думаю о представлении init метод, чтобы звонить сразу после создания и поместить все в фабрику функционирует как это:

boost::shared_ptr<a_class> create_a()
{
    boost::shared_ptr<a_class> ptr(new a_class);
    ptr->init();
    return ptr;
}

Прекрасен это или существует стандартная процедура для следования в таких случаях?

Править: На самом деле мой случай более сложен. У меня есть 2 объекта, которые должны поддержать указатели друг друга. Таким образом, истина, я не "регистрирую", но создаю другой объект (скажем, b_class) который требует this в качестве параметра. b_class получает this как слабый указатель и хранилища это.

Я добавляю это, потому что, так как Вы даете мне советы дизайна (которые очень ценятся), по крайней мере, можно знать то, что я делаю:

a_class::a_class()
{
    b = new b_class(this);
}

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

a_class ответственно за создание и уничтожение b_class экземпляры и таким образом поддерживает shared_ptr им, но b_class потребность управлять a_class и таким образом поддерживает слабый указатель. a_class экземпляр "выживает" b_class экземпляры.

Вы предлагаете избегать использования интеллектуальных указателей в этом случае?

29
задан Emiliano 4 August 2010 в 07:34
поделиться

3 ответа

a_class отвечает за создание и уничтожение b_class экземпляров

...

экземпляр a_class "выживает" экземпляры b_class.

Учитывая эти два факта, не должно быть опасности, что экземпляр b_class может попытаться получить доступ к экземпляру a_class после уничтожения экземпляра a_class, поскольку экземпляр a_class отвечает за уничтожение экземпляров b_class.

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

В этом примере не имеет значения, как создан a_class - динамически, как часть агрегированного объекта и т. д. Что бы ни создавало a_class, оно управляет его временем жизни, так же как a_class управляет временем жизни b_class, который оно инстанцирует.

Например,

class a_class;

class b_class
{
public:
    b_class( a_class* a_ ) : a( a_ ) {}
private:
    a_class* a;
};

class a_class
{
public:
    a_class() : b( new b_class(this) ) {}
private:
    boost::shared_ptr<b_class> b;
};

Обратите внимание, в этом игрушечном примере нет необходимости в shared_ptr, член объекта будет работать так же хорошо (при условии, что вы не копируете класс сущности).

class a_class
{
public:
    a_class() : b( this ) {}
private:
    b_class b;
};
8
ответ дан 28 November 2019 в 02:08
поделиться

Если вам абсолютно необходим shared_ptr во время построения, лучше всего иметь функцию 'init'. Фактически, это единственный достойный подход, о котором я могу думать. Вероятно, у вас должна быть специальная функция, которая создает объекты этого типа, чтобы гарантировать вызов init () , если вы выберете этот путь.

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

5
ответ дан 28 November 2019 в 02:08
поделиться

Почему бы вам не использовать http://www.boost.org/doc/libs/1_43_0/libs/smart_ptr/enable_shared_from_this.html

struct a_class : enable_shared_from_this<a_class> {
    a_class() {
        shared_ptr<a_class> ptr(this);
        register_somewhere(ptr);
    }
};

Обновление: вот полный рабочий пример:

#include <stdio.h>
#include <boost/smart_ptr/enable_shared_from_this.hpp>

struct a_class;
boost::shared_ptr<a_class> pa;

void register_somewhere(boost::shared_ptr<a_class> p)
{
    pa = p;
};

struct a_class : boost::enable_shared_from_this<a_class> {
private:
    a_class() {
        printf("%s\n", __PRETTY_FUNCTION__);
        boost::shared_ptr<a_class> ptr(this);
        register_somewhere(ptr);
    }

public:
    ~a_class() {
        printf("%s\n", __PRETTY_FUNCTION__);
    }

    static boost::shared_ptr<a_class> create()
    {
        return (new a_class)->shared_from_this();
    }
};

int main()
{
    boost::shared_ptr<a_class> p(a_class::create());
}

Обратите внимание на фабричную функцию a_class :: create (). Его задача - обеспечить создание только одного счетчика ссылок. Потому что

boost::shared_ptr<a_class> p(new a_class);

приводит к созданию двух счетчиков ссылок и двойному удалению объекта.

1
ответ дан 28 November 2019 в 02:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: