我可以 memcpy std::weak_ptr 吗?

Can I memcpy std::weak_ptr?

首先,std::weak_ptr 的典型实现是什么?特别是 std::weak_ptr 只是指向 std::shared_ptr 的控制块的指针?

如果所有std::shared_ptr引用都没有了,是不是删除了内部控制块?如果是这样,如果内存被重新利用,std::weak_ptr::expired() 如何正常工作?


我有一个包含 std::weak_ptr 的对象,我想将该对象 memcpy 到缓冲区以便稍后处理。这样做会以某种方式破坏智能指针的内部工作吗?

当所有 std::shared_ptr 对象都消失时,控制块仍然存在(这就是 std::weak_ptr 的工作方式),只有引用的对象被删除。

现在,可以通过 std::memcpy only if it is trivially copyable. Checking the requirements of TriviallyCopyable 概念安全地复制 C++ 对象,我们看到 std::weak_ptr 由于具有非平凡的复制构造函数而不能满足它。事实上,这个构造函数会增加控制块内的弱指针计数器,所以用 std::memcpy 复制它会破坏它的不变量。

老实说,在原始缓冲区中存储 std::weak_ptr 在通常的代码中听起来像是一个糟糕的主意。缓冲区通常用于序列化、sending/writing 数据等,所有这些任务对于智能指针来说都是无意义的。但是,如果您绝对确定需要将其存储在缓冲区中,则需要 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 };

注意new之后的(buffer):它告诉new不要分配内存,而是使用一个已经准备好的地方(因此place更换新的)。准备 buffer 时,请务必提供所需的大小和对齐方式。