【问题标题】:Can I memcpy std::weak_ptr?我可以 memcpy std::weak_ptr 吗?
【发布时间】:2023-03-20 03:44:01
【问题描述】:

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

如果所有std::shared_ptr 引用都消失了,是否删除了内部控制块?如果是这样,如果重新使用该内存,std::weak_ptr::expired() 将如何正常工作?


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

【问题讨论】:

  • en.cppreference.com/w/cpp/types/is_trivially_copyable#Notesstd::weak_ptr 有重要的构造函数,如果我没看错的话。
  • @Justin 非平凡构造函数的存在不是问题,只有非平凡的复制或移动构造函数存在。但是,实现不可能有一个简单的std::weak_ptr 复制构造函数,因为复制weak_ptr 需要修改控制块。
  • "特别是 std::weak_ptr 只是一个指向 std::shared_ptr 控制块的指针" 不是“是 a”而是 包含一个

标签: c++ c++11 shared-ptr weak-ptr data-representation


【解决方案1】:

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

现在,可以通过 std::memcpy only if it is trivially copyable 安全地复制 C++ 对象。检查TriviallyCopyable 概念的要求,我们看到std::weak_ptr 不满足它,因为它有一个非平凡的复制构造函数。事实上,这个构造函数会增加控制块内的weak-pointers-counter,所以用std::memcpy复制它会破坏它的不变量。

说实话,在原始缓冲区中存储std::weak_ptr 在通常的代码中听起来是个糟糕的主意。缓冲区通常用于序列化、发送/写入数据等,所有这些任务对于智能指针来说都是无意义的。但是,如果您绝对确定需要将其存储在缓冲区中,则需要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 不要分配内存,而是使用已经准备好的位置(因此placement new)。在准备buffer 时,请务必提供所需的大小和对齐方式。

【讨论】:

  • 原始缓冲区还有其他用途,例如optionalvariant。但这至少有点奇怪。但是,如果您确实需要将weak_ptr 复制到缓冲区中,那么正确的工具是放置新的。
  • @DanielH 非常好的一点!我会把这个添加到答案中,谢谢。
猜你喜欢
  • 2015-08-31
  • 1970-01-01
  • 2014-12-17
  • 2015-08-30
  • 1970-01-01
  • 2013-08-07
  • 1970-01-01
  • 2017-03-17
  • 2019-05-05
相关资源
最近更新 更多