【问题标题】:How to use shared_ptr to manage an object placed with placement new?如何使用 shared_ptr 管理放置新的对象?
【发布时间】:2021-04-25 10:29:48
【问题描述】:

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

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&lt;Thing&gt;(Thing::create(1))。但是,如果它在引用计数为空时调用 delete p.get() 的等价物,那将是未定义的,因为它与类型不匹配,更重要的是,不匹配复数 new 与单数删除。我需要它以特殊方式删除。

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

【问题讨论】:

  • shared_ptrplacement new组合的用例是什么?
  • 关于删除器的使用,cppreference有一个例子。
  • @prehistoricpenguin - 此结构通常用于具有严格内存限制的线程池系统,但如果shared_ptr 允许,我想在不太严格的上下文中使用相同的结构

标签: c++ memory-management shared-ptr


【解决方案1】:

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

【讨论】:

  • 我没想到要返回共享指针本身,这是一个巨大的改进,谢谢
猜你喜欢
  • 1970-01-01
  • 2014-01-11
  • 2011-02-06
  • 1970-01-01
  • 2021-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-14
相关资源
最近更新 更多