使用share_from_this而不是此指针

时间:2018-04-24 02:51:41

标签: c++ c++14 c++17

我想从类生成一个shared_ptr并使用它来代替this * raw指针来初始化另一个。另一个期望在Constructor中使用shared_ptr。我只展示了一段摘录:

class Soundfile : std::enable_shared_from_this<Soundfile> { ...more code

std::shared_ptr<Soundfile> Soundfile::getptr() {
     return  shared_from_this();
}

我需要从Soundfile初始化另一个名为Channel inside的类:

bool Soundfile::openRead(const char *filename_) { 
//more code ...
     channels = std::make_shared<Channel>(getptr() , windowSize_, gdata);
}

这不起作用,我成了一个weak_ptr例外,我试图做以下事情:

std::shared_ptr<Soundfile> Soundfile::getptr() {
    try {
        return shared_from_this();
    }
    catch (const std::bad_weak_ptr&) {
        return std::make_shared<Soundfile>();
    }
}

这样可行,但我成了一个新的空的shared_ptr,我将以前的数据保存在Soundfile类中,我需要在Channel中使用它,因为这不是我想要的。 我在这里搜索了一个解决方案,但我无法找到解决方案,如果问题重复,我很抱歉

编辑: 以下是我试图解释的最小例子:

class A : std::enable_shared_from_this<A> {
public:
    A() {}
    ~A() {}
    std::shared_ptr<A> getptr() {
        return shared_from_this();
    }
    void my_method() {
        myB = std::make_shared<B>(getptr());
    }
private:
    std::shared_ptr<B> myB;
};

class B {
public:
    B(std::shared_ptr<A> _myA)  {
        myA = _myA;
    }
    ~B() {}
private:
    std::shared_ptr<A> myA;
};

int main() {
    std::shared_ptr<A> myA = std::make_shared<A>();
    myA->my_method();

}

1 个答案:

答案 0 :(得分:4)

std::enable_shared_from_this::shared_from_this仅在实例当前由共享指针管理时才有效。

您可以将enable_shared_from_this视为包含weak_ptr的类。将从std::enable_shared_from_this派生的类的实例传递给shared_ptr构造函数时,该构造函数将初始化其中的weak_ptr。调用shared_from_this只会在弱指针初始化后才能工作,因为它是通过将weak_ptr转换为shared_ptr来实现的。

如果您在shared_from_this初始化之前致电weak_ptr,则会引发bad_weak_ptr异常,因为转化为shared_ptr失败。

为了解决您的问题,您必须确保在shared_ptr方法之前由getptr()管理Soundfile的任何实例,或者调用调用它的任何方法。

在极少数情况下我使用shared_from_this,我通常会将构造函数设为私有,并添加静态工厂方法以强制执行此操作:

class A {
    public:
        static std::shared_ptr<A> create() {
            return std::make_shared<A>();
        }
    private:
        A();
};

你仍然要小心你在构造函数中做了什么,因为shared_from_this在它们内部不起作用。