First off, what is the typical implementation of a std::weak_ptr
? Particularly is std::weak_ptr
just a pointer to the control block of a std::shared_ptr
?
If all the std::shared_ptr
references are gone is the internal control block deleted? If so, how does std::weak_ptr::expired()
function properly if that memory is re-purposed?
I have an object that contains a std::weak_ptr
, and I want to memcpy
the object to a buffer to be processed later. Is doing so going to break the internal workings of the smart pointer in some way?
When all std::shared_ptr
objects are gone, the control block still exists (that's how std::weak_ptr
's work), only the referenced object is deleted.
Now, a C++ object can be safely copied via std::memcpy
only if it is trivially copyable. Checking the requirements of TriviallyCopyable
concept, we see that std::weak_ptr
does not satisfy it due to having a non-trivial copy constructor. In fact, this constructor will increase the weak-pointers-counter inside the control block, so copying it with std::memcpy
would break its invariants.
To be honest, storing an std::weak_ptr
in a raw buffer sounds like a terrible idea in usual code. Buffers are normally used for serialization, sending/writing data, etc, and all these tasks are nonsensical for a smart pointer. If, however, you are absolutely sure that you need to store it in a buffer, you need placement new
:
std::weak_ptr<T> the_one_i_want_to_copy;
std::weak_ptr<T> * buffer = ...;
new (buffer) std::weak_ptr<T> { the_one_i_want_to_copy };
Notice the (buffer)
after new
: it tells new
not to allocate the memory, but to use an already prepared place (thus placement new). When preparing buffer
, be sure to provide the required size and alignment.