c++stlstdshared-ptrweak-ptr

Create std::weak_ptr to an indexed value of an array-type std::shared_ptr?


I have a large dataset which essentially loads like this:

for(int i=0;i<count; i++){
   auto ptr = std::make_shared<Object>(Object());
   //do stuff with ptr
}

This isn't great for performance, due to the memory allocation being piecemeal. What I want to do is this:

std::shared_ptr<Object[]> allObjects; //this is stored elsewhere until the program ends

allObjects.reset(new Object[count]);
for(int i=0;i<count; i++){
   auto ptr = std::weak_ptr<Object>(&allObjects[i]);
   //do stuff with ptr
}

This unfortunately doesn't compile. I can try it out like this:

auto ptr = std::shared_ptr<Object>(&allObjects[i]);

This works great while the program runs, but of course when all the copies of ptr get destroyed, there's hell to pay. So I would like ptr to be a std::weak_ptr. The main array std::shared_ptr will be stored until after all the weak_ptr are destroyed. So can I create a std::weak_ptr to an indexed member of an array-type std::shared_ptr? Am I just missing some syntax? Do I need a different container type? Or am I missing something fundamentally wrong with the approach?


Solution

  • You use the aliasing constructor of std::shared_ptr for this:

    auto ptr = std::shared_ptr<Object>(allObjects, &allObjects[i]);
    // and if you wanted a weak_ptr
    auto ptr = std::weak_ptr(std::shared_ptr<Object>(allObjects, &allObjects[i]));
    

    This ptr will use the same control block as allObjects (so it will have the same use_count and be destroyed at the same time, and crucially only once)