Усилить shared_from_this и деструктор - PullRequest
3 голосов
/ 14 декабря 2011

Я обнаружил, что нельзя вызывать shared_from_this в деструкторе из класса:

https://svn.boost.org/trac/boost/ticket/147

Такое поведение разработано. Поскольку деструктор уничтожит объект, небезопасно создавать для него shared_ptr, так как он станет зависшим после завершения деструктора.

Я понимаю аргумент, но что, если мне нужен указатель "shared_from_this" для очистки ссылок (не для совместного использования корабля владельца).

Вот пример, где я не использую shared_ptr:

class A{
public:
    A( Manager * m ) : m_(m) {
        m_->add(this);
    }

    ~A() {
        m_->remove(this);
    }

private:
    Manager * m_;
};

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

class A : public boost::enable_shared_from_this< A > {
public:
    typedef boost::shared_ptr< A > Ptr;

    static Ptr create( Manager * m ) {
        Ptr p( new A(m));
        p->init();
        return p;
    }

    ~A() {
        // NON-WORKING
        // m_->remove( shared_from_this() );
    }

private:
    A( Manager * m ) : m_(m) { }

    void init() {
        m_->add(shared_from_this());
    }

    Manager * m_;
};

Как я могу реализовать деструктор в примере выше?

Ответы [ 3 ]

4 голосов
/ 14 декабря 2011

Если у вашего менеджера есть shared_ptr для вашего объекта, то он владеет им. Таким образом, ваш объект не должен быть уничтожен, так как Менеджер все еще имеет ссылку на него.

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

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

Просто определите, кому действительно принадлежит объект, и передайте им shared_ptr. Если часть кода иногда нуждается в вашем объекте - если он существует - тогда присвойте ему слабый_птр.

3 голосов
/ 14 декабря 2011

Если у экземпляра Manager есть shared_ptr для вашего класса, ваш класс никогда не будет уничтожен, пока этот shared_ptr не исчезнет.Поэтому я предполагаю, что Manager на самом деле хранит слабый_птр в вашем экземпляре, и в этом случае API менеджера, вероятно, должен принимать слабый_птр, который вы должны иметь в деструкторе.Если вы не можете, просто сделайте один в своем конструкторе и сохраните его на потом.

1 голос
/ 15 декабря 2011

Здесь я попытался перевести его в общие указатели.

Не.

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

Зачем беспокоиться об умных указателях? потому что это модно?

weak_ptr часто неправильно понимают как класс, подобный указателю (это не так, это слабая ссылка).

weak_ptr редко подходит. (Даже с документацией Boost возникает путаница относительно того, когда weak_ptr подходит.)

enable_shared_from_this еще проще понять.

...