Reputation: 13002
A fairly common thing I need to do is allot an object and some memory it'd like, in a strictly contagious region of memory together:
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;
}
In Thing::Create()
this is done with placement new into a section of memory.
I'd also like to have a shared pointer manage it in this case, using auto p = shared_ptr<Thing>(Thing::create(1))
. But If it calls the equivalent of delete p.get()
when the ref count empties, that'd be undefined as it mismatches the type and, more importantly, mismatches plural new with singular delete. I need it to delete in a special way.
Is there a way to easily set that up without defining an outside function? Perhaps by having the shared pointer call Thing::destroy()
when the ref count empties? I know that shared pointer can accept a "deleter" as a template argument, but I'm unsure how to use it, or if it's even the proper way to address this?
Upvotes: 1
Views: 346
Reputation: 30494
std::shared_ptr
accepts a deleter function as a second parameter, so you can use that to define how the managed object will be destroyed.
Here's a simplified example:
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();
}
Upvotes: 2