多个shared_ptrs到同一个对象,一个被损坏

时间:2016-05-30 17:53:04

标签: c++ shared-ptr

我编写了一个程序,我在其中使用shared_ptr来存储图形的节点。每个节点都有另一个关联的对象,它将shared_ptr保存到它所属的节点。看起来这不是正确的方法,因为孩子的父母的shared_ptr被卡住了(当我在构建之后创建更多的父母的shared_ptrs时,use_count()不会增加)。

ideone demo

父母:

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(没有新的)创建Parent并通过getptr()获取shared_ptr时,一切都按预期工作。有人可以详细说明吗?我做了些蠢事吗?

提前致谢!

1 个答案:

答案 0 :(得分:2)

问题是您创建了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; } 使用现有的控制块。

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

Coliru上的输出是:

shared_ptr<Parent> p(new Parent);

你犯这个错误的第一个线索应该是:func mapView(mapView: GMSMapView, idleAtCameraPosition position: GMSCameraPosition) { navigationController?.setNavigationBarHidden(false, animated: true) } func mapView(mapView: GMSMapView, willMove gesture: Bool) { print("Will move") navigationController?.setNavigationBarHidden(true, animated: true) } 你的计数都是1和1,它应该是2,因为你有2个共享指针到1个父对象。

P.S:话虽如此,我不确定这是你想要实现的最佳设计,但这是另一个问题/辩论。