Ziqi Liu
Ziqi Liu

Reputation: 3171

C++ use shared_ptr for continuous allocated memory

I want to create some continuous memory, and use bunch of shared_ptr pointing to them.

int main() {
  int *arr = new int[5];
  for (int i = 0; i < 5; i++) {
    std::shared_ptr<int> ptr(&arr[i]);
  }// when the loop scope end, the shared_ptr will be destroyed. 
};

this code will give an error:

pointer being freed was not allocated

my expectation: when the scope of loop end, the shared_ptr will be destroy, and the element in array will be destroyed successively.

But it seems that when the first pointer is destroyed, the whole array is freed.

I also tried std::allocator, still not work.

So is there any way that can allocate continuous memory, and I can use shared_ptr pointing to each of them, then when the first element is freed, the whole memory won't be freed together?

Upvotes: 0

Views: 1283

Answers (2)

Alan Birtles
Alan Birtles

Reputation: 36389

Its an "interesting" thing to want to do but if you really want to do it you can use the shared_ptr's aliasing constructor.

int main() {
  std::shared_ptr<int[]> arr(new int[5]);
  for (int i = 0; i < 5; i++) {
    std::shared_ptr<int> ptr(arr,&arr[i]);
  }
};

Without c++17 you need to do a little more:

int main() {
    std::shared_ptr<int[]> arr(new int[5], std::default_delete<int[]> {});
    for (int i = 0; i < 5; i++) {
        std::shared_ptr<int> ptr(arr, &arr.get()[i]);
    }
};

The array will be deleted when the last element shared_ptr is destroyed (assuming the array shared_ptr itself has already been destroyed/reset).

Upvotes: 4

Rerito
Rerito

Reputation: 6086

You are misusing shared_ptr. The memory you allocated was attributed with operator new[], it should thus be freed with operator delete[].

Furthermore, since the allocated object is an array, any ownership semantics should be applied to the whole array and not divided across its elements!

You can achieve by specifying a custom deleter for your shared_ptr: (C++11/14)

std::shared_ptr<int> arr_ptr(new int[5], std::default_delete<int[]> {});

Or simply using an array type specialization of shared_ptr (C++17):

std::shared_ptr<int[]> arr_ptr(new int[5]); // Will call delete[] upon destruction.

Upvotes: 3

Related Questions