Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set shared_ptr with new_pointer that is old_pointer + offset

Here is a smart pointer: std::shared_ptr<char> p(new char[size]) which represents array filled with raw binary file content. After (and only after) the whole array is copied from file to RAM, I can parse it, and during this I retrieve some header information (a few first dwords). Then actual data follows.

Without giving much more context, it's handy for me to to set mentioned shared pointer to new address that is beginning of actual data. This address is still in alocated memory. But how to set without losing it?

A question is (yes/no): Is it possible to set p to offset of prevous pointer, without invoking deletion of data?

like image 423
Alexey Larionov Avatar asked Feb 17 '19 20:02

Alexey Larionov


People also ask

Why would you choose shared_ptr instead of Unique_ptr?

In short: Use unique_ptr when you want a single pointer to an object that will be reclaimed when that single pointer is destroyed. Use shared_ptr when you want multiple pointers to the same resource.

What does shared_ptr get () do?

std::shared_ptr::getReturns the stored pointer. The stored pointer points to the object the shared_ptr object dereferences to, which is generally the same as its owned pointer.

When should you use shared_ptr?

So, we should use shared_ptr when we want to assign one raw pointer to multiple owners. // referring to the same managed object. When to use shared_ptr? Use shared_ptr if you want to share ownership of a resource.

Can you move a shared_ptr?

Copying a shared_ptr involves copying its internal state object pointer and changing the reference count. Moving it only involves swapping pointers to the internal reference counter, and the owned object, so it's faster.


1 Answers

Yes this is possible. You can use constructor 8, the aliasing constructor from this reference: https://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr

// make sure you use an array deleter std::shared_ptr<char> osp(new char[1024], std::default_delete<char[]>());  // load the data into your buffer at osp.get()  // Find the offset in the data by parsing auto const offset = parse_buffer_for_offset(osp.get());  // Now set a new offset into the data std::shared_ptr<char> nsp(osp, osp.get() + offset); 

Now nsp.get() returns the offset address but the original array will get deleted properly.

Note: The offset is a property of each shared_ptr so if you copy the shared_ptr nsp you get another shared_ptr with the same offset. This works whether you construct a new copy or assign a copy to an existing shared_ptr.

This means you can have different shared_ptr with different offsets that all manage the same, underlying resource which will only be cleaned up after all shared_ptr are destroyed.

To see this in operation consider the following code:

std::shared_ptr<char> original_sp(new char[1024], std::default_delete<char[]>());  std::shared_ptr<char> offset_100_sp1(original_sp, original_sp.get() + 100); std::shared_ptr<char> offset_100_sp2 = offset_100_sp1;  std::shared_ptr<char> offset_200_sp1(original_sp, original_sp.get() + 200); std::shared_ptr<char> offset_200_sp2 = offset_200_sp1;  std::cout << "\nPointers managing the array: " << original_sp.use_count() << '\n';  std::cout << "\nOffset 100 pointers:" << '\n'; std::cout << std::distance(original_sp.get(), offset_100_sp1.get()) << '\n'; std::cout << std::distance(original_sp.get(), offset_100_sp2.get()) << '\n';  std::cout << "\nOffset 200 pointers:" << '\n'; std::cout << std::distance(original_sp.get(), offset_200_sp1.get()) << '\n'; std::cout << std::distance(original_sp.get(), offset_200_sp2.get()) << '\n'; 

Output:

Pointers managing the array: 5  Offset 100 pointers: 100 100  Offset 200 pointers: 200 200 
like image 145
Galik Avatar answered Sep 18 '22 13:09

Galik