shared_pointer 意外行为

shared_pointer unexpected behaviour

有一段代码:

A.cpp

class MySomeClass: public SomeClass
{
   public: 
   void specificMethod();
}

class A
{
    public:
    A::A();

    std::shared_ptr< B > m_bObject;
    std::shared_ptr< MySomeClass > m_argument;
}

A::A()
{
    m_argument= std::make_shared< MySomeClass >();
    m_bObject = std::make_shared< B >( m_argument);
}

B.cpp

B::B(const std::shared_ptr< SomeClass >& smartOne):m_smartOne(smartOne)
{}

B::someMethod()
{
    m_smartOne->specificMethod();
}

B.h

class B
{
public:
    B(const std::shared_ptr< SomeClass >& smarOne);
    void someMethod();

private:
    const std::shared_ptr< SomeClass >& m_smartOne;
};

问题是当我调用 m_bObject->someMethod() 时出现核心转储,因为 m_smartOne 不是 MySomeClass 而是 SomeClass.
为什么?是范围问题、所有权问题还是其他?
我收到了 B class 的代码,无法更改。

std::make_shared<B>(m_argument)构造B对象时,它将从m_argument创建一个临时shared_ptr<SomeClass>对象,类型为shared_ptr<MySomeClass>。对该临时对象的引用被传递给 B 的构造函数,该构造函数存储一个引用,该引用在构造函数调用完成后临时对象被销毁时立即变为悬空。

使用悬空引用的结果当然是未定义的行为。什么事都有可能发生。

如果您无法触及 B,那么最好的办法可能是让 A 存储一个 shared_ptr<SomeClass> 成员,这样就不会创建临时文件。但即便如此 A 也会有效地将引用存储到自身中,这意味着默认的 copy/move 构造函数和赋值运算符都会做错事情。那是一个巨大的蠕虫罐头。