我正在尝试将shared_ptr用于其自身内部结构的父节点。从这种数据类型派生时,我希望将父指针转换为派生类型。
以下是我尝试使用的代码。
#include <iostream>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/make_shared.hpp>
using boost::shared_ptr;
using boost::weak_ptr;
using boost::dynamic_pointer_cast;
using boost::make_shared;
struct A
{
weak_ptr<A> parent;
int i;
virtual ~A() {}
};
struct B : virtual A
{
int j;
virtual ~B() {}
};
int main(int argc, char *argv[])
{
B a, b;
a.i = 1;
a.j = 2;
b.i = 4;
b.j = 8;
b.parent = weak_ptr<B>(make_shared<B>(a));
// ^^^
// The problem is here, not where I had
// thought it was earlier.
shared_ptr<B> pb;
if (pb = dynamic_pointer_cast<B>(b.parent.lock()))
{
// This is the code block that is intended to run
// but the control does not flow here.
std::cout << "b's parent: " << pb->i << ' '
<< pb->j << "\n";
}
else
{
std::cout << "Could not lock shared pointer or Pointer Null" << "\n";
}
return 0;
}
输出`失败&#39;以下消息
Could not lock shared pointer or Pointer Null
请解释一下行为
更新
在我从解释中得知之后,我改变了标题,这实际上是误导。
对我来说,来自@Igor的以下comment解释得最好。
make_shared<B>(a)
创建一个临时shared_ptr
,即 在分号处被摧毁。您将其分配给weak_ptr
- 但是 仅weak_ptr
并不能使对象保持活力
答案 0 :(得分:4)
b.parent = weak_ptr<B>(make_shared<B>(a));
在此行中,您创建一个shared_ptr
,它在同一行上死亡。
weak_ptr
仅存储对它的弱引用,因此它不会被计为增加计数器的正常引用。
因此,当您使用lock
的{{1}}方法时,它会返回一个空的weak_ptr
。
答案 1 :(得分:1)
shared_ptr
此行创建指向b.parent = weak_ptr<B>(make_shared<B>(a));
副本的临时共享指针,并将指向它的弱指针指定给a
然后临时共享指针被销毁,使b.parent
指向被破坏的指针,因此任何b.parent
的尝试都会失败。
答案 2 :(得分:1)
当您拨打以下电话时:
b.parent = weak_ptr<B>(make_shared<B>(a));
指定弱指针后指针就会被破坏,因为弱指针不会试图让对象保持活动状态。
记住,如果对象没有更多的shared_ptr,指针将破坏对象,指针将变为无效。这是智能指针的想法。
此外,您正在混合指针和非指针对象,这很糟糕并且可能导致问题:请注意,对make_shared<B>(a)
的调用将调用B
的复制构造函数来创建新的实例从B
复制的课程a
。所以它并不是b
的父级,尽管你希望它是。{/ p>
我建议完全转移到智能指针
int main()
{
shared_ptr<B> a = make_shared<B>();
shared_ptr<B> b = make_shared<B>();
a->i = 1;
a->j = 2;
b->i = 4;
b->j = 8;
b->parent = a;
shared_ptr<B> pb;
if (pb = dynamic_pointer_cast<B>(b->parent.lock())) {}
}