容器对象传递为(void *)时的共享指针行为

时间:2015-05-29 10:57:36

标签: c++ c++11 memory-management shared-ptr void-pointers

我的类对象(ObjA)中有shared_ptr变量。需要将此对象存储为另一个Class对象(ObjB)的(void *)实体。

我的问题是,shared_ptr的行为是什么(将释放关联的堆内存?它的引用计数会发生什么?) -

  1. 当ObjA转换为void *

  2. 当void * ObjB的实体被强制转换为(ClassA *)

  3. 简化代码:

    Class AA{
    
        shared_ptr<int> aptr;
    
        public:
            AA(){
                aptr = make_shared<int>(100);
            }
            shared_ptr<int> get_aptr(){
                return aptr;
            }
    };
    
    
    Class BB{
    
        void *smpl;
    
        public:
    
            void setter(void* p){
                smpl = p;
            }
    
            void* getter(){
                return smpl;
            }
    };
    
    int main(){
    
        AA *objA = new AA();
        BB *objB = new BB();
    
        objB->setter(objA);
        //status of allocated int in class AA here?
    
        //some code later
        AA *objA_2 = (AA*)objB->getter();
        //status of allocated int in class AA here?
    
        shared_ptr<int> p2 = objA_2->get_aptr();
        //is this allowed
    
    }
    

    我主要担心的是如何释放shared_ptr的内存。 (鉴于它包含在void *对象中,无法删除 - shared_ptr始终保持在范围内) 我尝试删除objB,并在析构函数 -

    中使用适当的转换为其组件void *
    BB::~BB(){
        delete (*AA)smpl;
    }
    

    但这是错误,因为类AA中的shared_ptr变量不允许显式删除 - 只有当它超出范围时才释放其分配的区域。 (在这种情况下,它永远不知道它何时超出范围!)

    此外,BB类是第三方类 - 我无法修改smpl成员变量的类型void *(Node类中的_userData变量,在Cocos2dx中)。 请帮助解决此内存泄漏..

1 个答案:

答案 0 :(得分:0)

此处void *用作观察指针。它根本不影响共享指针,因为共享指针不知道甚至存在指向其包含对象的原始指针。

如果您选择shared_ptr<void>而不是原始指针(并通过原始共享指针构造它,例如,您的setter应由void setter(std::shared_ptr<void> const& p)替换),那将会有所不同。

在这种情况下,引用计数受到影响,并且将确保指向对象的生存。关于此选项,请参阅here

编辑:从您的评论中,您似乎正在寻找与以下内容类似的设置:

struct AA
{
    //...
};


struct BB
{
    std::shared_ptr<void> smpl;

    void setter(std::shared_ptr<void> const& p)
    {
        smpl = p;  //now the ref count of your shared_tr to AA is increased
    }
};

int main()
{    
    auto objA = std::make_shared<AA>();
    auto objB = std::make_shared<BB>();

    objB->setter(objA);

    std::cout<<objA.use_count()<<std::endl;   //prints "2"
}

DEMO

调用setter后的引用计数为2shared_ptr<void>就像一个普通的共享指针一样,它使AA - 对象保持活着状态,或者如果指针超出范围则正确地销毁它对象(并且它本身是最后一个指向给定的对象) AA)。

这样可行,因为已经复制了原始共享指针的删除程序,它知道要销毁谁。

EDIT2:要回答OP代码中的问题:

objB->setter(objA);
//status of allocated int in class AA here?

AA内的共享指针根本不受影响。

//some code later
AA *objA_2 = (AA*)objB->getter();
//status of allocated int in class AA here?

同样,共享指针不受影响。但是,这一步需要小心:如果原始对象不再存在,您将获得一个悬空指针。因此,最好使用共享指针。

shared_ptr<int> p2 = objA_2->get_aptr();
//is this allowed

当然,如果指针有效。

我没有得到的一件事是为什么你在课堂上使用智能指针,但在外面使用原始指针。这有什么理由吗?