shared_pointer意外行为

时间:2017-07-05 08:42:01

标签: c++ c++11 smart-pointers

有一段代码:

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课程的代码,但无法更改。

1 个答案:

答案 0 :(得分:2)

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

使用悬空引用的结果当然是未定义的行为。任何事情都可能发生。

如果您无法触摸B,那么您可以做的最好的事情可能是A存储shared_ptr<SomeClass>成员,以便不会创建临时成员。但即便如此A也会有效地将引用存储到自身中,这意味着默认的复制/移动构造函数和赋值运算符都会做错误的操作。这是一个巨大的蠕虫病毒。