我写了一个程序,我利用shared_ptr来存储图形的节点。每个节点都有另一个关联的对象,该对象保持对它所属节点的shared_ptr。这似乎不是正确的方法,因为孩子对父级的shared_ptr卡住了(当我在构造后创建父级的更多shared_ptrs时,use_count() 不会增加)。
IDEe演示
父级:
struct Parent : public enable_shared_from_this<Parent>
{
Child myChild;
Parent() :
myChild(shared_ptr<Parent>(this)) // can't use getptr() here -> bad_weak_ptr
{}
shared_ptr<Parent> getptr()
{
return shared_from_this();
}
};
孩子:
struct Child
{
shared_ptr<Parent> ptr;
Child(shared_ptr<Parent> a) :
ptr(a)
{}
};
测试:
shared_ptr<Parent> p(new Parent);
cout << "UC of parent: " << p.use_count() << endl;
cout << "UC of child ptr: " << p->myChild.ptr.use_count() << endl;
shared_ptr<Parent> p2(p);
cout << "UC of parent: " << p2.use_count() << endl;
cout << "UC of child ptr: " << p2->myChild.ptr.use_count() << endl;
输出:
UC of parent: 1
UC of child ptr: 1
UC of parent: 2
UC of child ptr: 1 // expected 2!
我注意到当我通过其正常的 ctor 创建父级(没有新)并通过 getptr() 获取shared_ptr时,一切都按预期工作。有人可以详细说明一下吗?我在做傻事吗?
提前感谢!
问题是您创建了 2 个不同的内存控制块。一个在子对象中,方法是让它创建对 Parent 对象的shared_pointer,然后使用 newed
指针手动创建shared_pointer,而不是调用 getptr()
进而调用重用现有控制块的shared_from_this
。
#include <iostream>
#include <memory>
using namespace std;
struct Parent;
struct Child
{
shared_ptr<Parent> ptr;
Child(Parent* a) :
ptr(a)
{}
};
struct Parent : public enable_shared_from_this<Parent>
{
Child myChild;
Parent() :
myChild(this)
{}
shared_ptr<Parent> getptr()
{
return shared_from_this();
}
};
int main()
{
shared_ptr<Parent> p = (new Parent)->getptr(); // <-- The mistake was not using shared_from_this here, this creating 2 unrelated use counts for the same object
cout << "UC of parent: " << p.use_count() << endl;
cout << "UC of child ptr: " << p->myChild.ptr.use_count() << endl;
shared_ptr<Parent> p2(p);
cout << "UC of parent: " << p2.use_count() << endl;
cout << "UC of child ptr: " << p2->myChild.ptr.use_count() << endl;
return 0;
}
Coliru 上的输出是:
g++ -std=c++14 main.cpp && ./a.out
UC of parent: 2
UC of child ptr: 2
UC of parent: 3
UC of child ptr: 3
这个错误的第一个线索应该是:shared_ptr<Parent> p(new Parent);
你的计数都是 1 和 1,它应该是 2,因为你有 2 个指向 1 Parent 对象的共享指针。
PS:话虽如此,我不确定这是你想要实现的最佳设计,但这是一个完全不同的问题/辩论。