在类中存储单例指针

时间:2018-10-23 15:49:55

标签: c++

我正在调试一些代码,并且遇到了崩溃的代码片段,问题是单例指针和本地指针不是同一地址。我不确定为什么会这样。

代码大致如下:

class B;

class I_A : public std::enable_shared_from_this<I_A> {
    public:
    virtual std::shared_ptr<B> make() = 0;
};

class A : public I_A {
  public:
    std::shared_ptr<B> make() override {
        return std::make_shared<B>(shared_from_this());   
    }
};

static std::shared_ptr<I_A> getInstance() {
    static std::shared_ptr<I_A> ptr;
    if(!ptr) {
        std::cout << "Making new instance\n";
        ptr = std::make_shared<A>();   
    }
    std::cout << "Ptr is " << ptr << '\n';
    return ptr;
}

class B {
    public:
    B(const std::shared_ptr<I_A>& ptr) : ptr(ptr) {
        std::cout << "In B() " << ptr << '\n';
    }

    void foo() {
        std::cout << "B::ptr " << ptr << '\n';
        assert(ptr == getInstance());   
    }

    private:
        const std::shared_ptr<I_A>& ptr; // Potential problem here
};


int main() {
    auto bPtr = getInstance()->make();
    bPtr->foo();
}

但是,如果我将shared_ptr<I_A>的副本存储在B中而不是存储引用,则一切正常。

如果我的理解是正确的,则单例永远不要更改地址,但是B::ptrgetInstance()的地址不同。

知道为什么吗?

1 个答案:

答案 0 :(得分:6)

对于任何const std::shared_ptr<T>&,您应该(大约)从不使用T。只需使用std::shared_ptr<T>。您会使用T * const &吗?

您正在观察的问题是,您从std::shared_ptr<I_A>获得的A::shared_from_this()实例是临时的,并且在您可以使用时已经不复存在您的B。然后,您使用悬挂的参考,其行为不确定。