弱指针分配失败

时间:2016-01-26 14:59:19

标签: c++ shared-ptr

我正在尝试将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

请解释一下行为

更新

  1. 在我从解释中得知之后,我改变了标题,这实际上是误导。

  2. 对我来说,来自@Igor的以下comment解释得最好。

  3.   

    make_shared<B>(a)创建一个临时shared_ptr,即   在分号处被摧毁。您将其分配给weak_ptr - 但是   仅weak_ptr并不能使对象保持活力

3 个答案:

答案 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())) {}
}