微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何使用 shared_ptr 来管理放置新放置的对象?

如何解决如何使用 shared_ptr 来管理放置新放置的对象?

我需要做的一件相当常见的事情是将一个对象和它想要的一些内存分配到一个严格传染的内存区域中:

class Thing{
    static_assert(alignof(Thing) == alignof(uint32),"party's over");
public:
   
    ~Thing(){
        //// if only,but this would result in the equivalent of `free(danglingPtr)` being called
        //// as the second stage of shared_ptr calling `delete this->get()`,which can't be skipped I believe? 
        // delete [] (char*)this;
    }

    static Thing * create(uint32 count) {
        uint32 size = sizeof(Thing) + sizeof(uint32) * count; // no alignment concerns
        char * data = new char[size];
        return new (data)Thing(count);
    }
    
    static void destroy(Thing *& p) {
        delete [] (char*)p;
        p = NULL;
    }

    uint32 & operator[](uint32 index) {
        assert(index < m_count);
        return ((uint32*)((char*)(this + sizeof(Thing))))[index];
    }

private:
    Thing(uint32 count) : m_count(count) {};
    uint32 m_count;
};

int main(){
    {
        auto p = shared_ptr<Thing>(Thing::create(1));
        // how can I tell p how to kill the Thing?
    }
    return 0;
}

Thing::Create() 中,这是通过将 new 放置到一段内存中来完成的。

在这种情况下,我还希望有一个共享指针来管理它,使用 auto p = shared_ptr<Thing>(Thing::create(1))。但是如果它在引用计数为空时调用 delete p.get() 的等价物,那将是未定义的,因为它与类型不匹配,更重要的是,将复数 new 与单数 delete 不匹配。我需要它以特殊方式删除

有没有办法在不定义外部函数的情况下轻松设置它?也许通过在引用计数为空时让共享指针调用 Thing::destroy() ?我知道共享指针可以接受“删除器”作为模板参数,但我不确定如何使用它,或者它是否是解决此问题的正确方法

解决方法

std::shared_ptr 接受删除器函数作为第二个参数,因此您可以使用它来定义如何销毁托管对象。

这是一个简化的例子:

class Thing
{
public:
    ~Thing()
    {
        std::cout << "~Thing\n";
    }

    static std::shared_ptr<Thing> create() {
        char * data = new char[sizeof(Thing)];
        Thing* thing = new (data) Thing{};
        return std::shared_ptr<Thing>{thing,&Thing::destroy};
    }
    
    static void destroy(Thing* p) {
        p->~Thing();
        delete [] (char*)p;
    }
};

int main()
{
    auto p = Thing::create();
}

Live Demo

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。