对同一对象的多个shared_ptrs,一个已损坏



我写了一个程序,我利用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:话虽如此,我不确定这是你想要实现的最佳设计,但这是一个完全不同的问题/辩论。

相关内容

最新更新