加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 将shared_ptr转换为常规指针

发布时间:2020-12-16 10:13:46 所属栏目:百科 来源:网络整理
导读:我们有一个函数,它返回一个新的已分配对象作为输出参数(引用指针). MyFunc(MyObject* obj){ obj = new MyObject();} 这样称为: Object* obj;MyFunc(obj); 在内部,该函数执行了相当多的操作,并使用shared_ptr进行内存管理.完成后,我们想要返回的对象由shared
我们有一个函数,它返回一个新的已分配对象作为输出参数(引用指针).

MyFunc(MyObject*& obj)
{
    obj = new MyObject();
}

这样称为:

Object* obj;
MyFunc(obj);

在内部,该函数执行了相当多的操作,并使用shared_ptr进行内存管理.完成后,我们想要返回的对象由shared_ptr引用.我正在努力如何将我们的新分配对象作为常规指针返回.

我们希望继续在内部使用shared_ptr来降低风险,但是返回一个shared_ptr似乎没有意义,因为调用者对返回的值拥有完全的所有权(被调用的函数或对象不再需要或保持对返回数据)我们希望它们具有灵活性.

有没有人有任何建议允许我们在内部使用shared_ptr但有一个常规指针接口?谢谢

解决方法

如果由于某种原因你不能/不想使用std :: unique_ptr或std :: auto_ptr(例如,如果你因为某些原因需要在创建过程中在内部拥有多个所有者,或者你的底层方法需要传递std :: shared_ptr),您仍然可以使用自定义删除器使其与std :: shared_ptr一起使用,如下所述: https://stackoverflow.com/a/5995770/1274747

原则上,在返回之前完成后,将切换器切换为不实际删除实例(使删除器为“null”),然后通过shared_ptr get()返回.即使在所有shared_ptr对象被销毁之后,内存也不会被删除(因为删除的删除器将跳过删除).

评论中还有一个链接不太明显,这可能是您感兴趣的:
http://paste.ubuntu.com/23866812/
(不确定,如果在没有所有情况下交换机的共享所有权的情况下它真的可行,则需要测试)

编辑

正如预期的那样,使用来自pastebin的链接简单的可拆卸删除器需要小心,因为删除器实际上被复制以存储在std :: shared_ptr中.

但你仍然可以通过使用std :: ref使其工作:

MyFunc(MyObject*& obj)
{
    DisarmableDelete<MyObject> deleter;
    std::shared_ptr<MyObject> ptr(new MyObject(),std::ref(deleter));
    // do what is necessary to setup the object - protected by deleter
    // ...
    // disarm before return
    deleter._armed = false;
    obj = ptr.get();
    // deleter disarmed - object not freed
}

而且为了完整性(并避免潜在的未来破坏链接),这里是从http://paste.ubuntu.com/23866812/开始实施的DisarmableDelete.

template <typename T,typename Deleter = typename std::default_delete<T> >                                                                                                                              
    struct DisarmableDelete : private Deleter {                                                                                                                                                         
        void operator()(T* ptr) { if(_armed) Deleter::operator()(ptr); }                                                                                                                                
        bool _armed = true;                                                                                                                                                                             
    };

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读