增强 shared_from_this 和析构函数

4
我发现在一个类的析构函数中,调用 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_;
};

如何在上述示例中实现析构函数?

我想创建新的标签:misuse-of-weak-ptr 和 misunderstanding-of-enabled-shared-from-this。 - curiousguy
3个回答

5
如果你的经理有一个shared_ptr指向你的对象,那么它就拥有了该对象。 因此,你的对象不应该被销毁,因为经理仍然持有对它的引用。
你可以向经理传递一个弱指针,但这时经理的工作就是检查指针是否仍然有效,如果无效则删除它。
你的问题很有趣,但你的情况是由一个误解引起的。只要一个对象拥有对你的对象的引用,那么shared_ptr的目的就是不会销毁它。为了调用析构函数,你应该手动调用指针上的delete,这是使用shared_ptr时的一种不好的行为。
简单地确定谁真正拥有该对象,并给他们shared_ptr。如果代码中的某个部分偶尔需要你的对象-如果它存在的话-则给它一个weak_ptr即可。

3
如果Manager实例拥有指向您的类的shared_ptr,则只要该shared_ptr存在,您的类就永远不会被销毁。因此,我假定Manager实际上是存储指向您实例的weak_ptr,那么Manager的API应该接受一个weak_ptr,并且您应该能在析构函数中获取它。如果无法获取,只需在构造函数中创建并存储它即可。

按设计,weak_ptr 用于让对象被销毁。因此,拥有 weak_ptr 的对象需要检查其有效性。 但是这仍然是一个好的解决方案。 - Geoffroy
只是试图提供一些选项,针对你指出的一个有点误解的问题,即我们不应该在析构函数中从持有我们 shared_ptr 的对象中注销自己。 - Matthew Walton
2
你好。"一个weak_ptr,你应该能够在析构函数中获取它" --- 你能解释一下,在析构函数中如何获取weak_ptr吗?enable_shared_from_this只包含shared_from_this,没有weak_from_this... - hate-engine
@hate-engine,C++17终于支持weak_from_this了。 - rwols
@rwols 你会如何使用它? - curiousguy
一个使用案例是在对象销毁时移除其缓存的弱指针。该对象现在可以通过其 weak_from_this() 参数触发信号,让其他对象知道它即将消失。 - rwols

2

在这里,我尝试将其翻译为共享指针。

不要这样做。

你的第一个类很好(除了它是一个隐式声明的复制构造函数和复制赋值 - 与使用原始指针无关)。

为什么要费心去使用智能指针?只是因为它很流行吗?

weak_ptr 经常被误解为指针类(实际上它不是,它是一个弱引用的东西)。

weak_ptr 很少适用。 (即使 Boost 文档也会让人困惑,不知道何时使用 weak_ptr 是合适的。)

enable_shared_from_this 更容易被误解。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接