智能指针,为什么在更改底层对象之前需要检查我是否是唯一用户?

Smart pointer, why need to check if I am the only user before changing the underlying object?

我正在阅读 C++ Primer,发现这些内容有点令人困惑:

The reset member is often used together with unique to control changes to the object shared among several shared_ptrs. Before changing the underlying object, we check whether we’re the only user. If not, we make a new copy before making the change:

if (!p.unique())
    p.reset(new string(*p)); // we aren't alone; allocate a new copy
*p += newVal; // now that we know we're the only pointer, okay to change this object

上面引用的文字中强调的文字是什么意思?好迷茫。

更新:

再看一遍课文,我发现我可能漏掉了什么。

所以根据上面的代码,我们假设有2 shared_ptr(一个是这里提到的p)指向原始动态内存对象比方说A .然后如果我想修改对象A,我分配一个新的动态内存,复制值为A(new string(*p)),分配给p,假设B。所以最终 A 没有被修改,而只是创建了 A?

的修改版本的副本

为什么不直接做*p += newVal;?为什么它与答案中提到的 Copy-on-write 有关?我的意思是,不需要额外的复制操作。所有 shared_ptr 最初都指向动态内存对象 A。只有 1 个对象。


可能提供更多上下文的屏幕截图:

因为您只能修改 shared_ptr 而不能修改它们引用的对象。这是为了防止数据竞争。

来自util.smartptr.shared/4

For purposes of determining the presence of a data race, member functions shall access and modify only the shared_­ptr and weak_­ptr objects themselves and not objects they refer to.

Changes in use_­count() do not reflect modifications that can introduce data races.

对于reset()成员函数:

void reset() noexcept;

Effects: Equivalent to shared_­ptr().swap(*this).

更新:根据新知识进行了大量修订。


简答(针对您的问题的标题):您没有。你在读什么 C++ 入门书?不可能是你在那里引用的例子 primer material.

智能指针背后的整个思想是 'just work',一旦您正确理解了它们,这篇文章的作者就在这里搞了一个噱头,这种噱头很少(如果有的话)在实践中使用。

他似乎试图描述某种在软件中实现的 oh-so-slightly-weird copy-on-write 机制,但他显然已经迷惑了 OP,毫无疑问,他的大多数其他读者也这样做了.这一切都有点愚蠢,而且不值得去理解为什么他们会像现在这样呈现它(或者,实际上,它首先应该做什么)。就像我说的,它在入门书(或其他任何地方)中没有位置。

无论如何,std::shared_ptr::unique() 是有缺陷的(它不是线程安全的)并且将是 going away soon。 它可能一开始就不应该存在,不要使用它。

在线程的各种讨论中出现了另一个问题,那就是改变由 shared_ptr 管理的 object 是否安全。那么你从哪里得到它不是的概念? 当然的是。如果你不能,很多程序根本就写不出来。只是不要同时从两个不同的线程改变相同的 object(这就是标准所称的 数据竞争 )——这是唯一的问题。如果您确实想这样做,请使用互斥锁。

我认为本书的作者在这里描述了如何使用 shared_ptr 实现 Copy-on-write 范式。正如 "this isn't a requirement of shared_ptr, its simply a design decision".

之前的评论中提到的