有一段代码:
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
课程的代码,但无法更改。
答案 0 :(得分:2)
当std::make_shared<B>(m_argument)
构造B
对象时,它将从shared_ptr<SomeClass>
创建一个临时m_argument
对象,其类型为shared_ptr<MySomeClass>
。对该临时文件的引用传递给B
的构造函数,该构造函数存储一个引用,该引用在构造函数调用完成后销毁临时对象时立即变为悬空。
使用悬空引用的结果当然是未定义的行为。任何事情都可能发生。
如果您无法触摸B
,那么您可以做的最好的事情可能是A
存储shared_ptr<SomeClass>
成员,以便不会创建临时成员。但即便如此A
也会有效地将引用存储到自身中,这意味着默认的复制/移动构造函数和赋值运算符都会做错误的操作。这是一个巨大的蠕虫病毒。