C++ ::lock()函数如何在std::weak_ptr上工作?

C++ ::lock()函数如何在std::weak_ptr上工作?,c++,smart-pointers,weak-ptr,C++,Smart Pointers,Weak Ptr,当您的ptr较弱时,您会: std::weak_ptr<int> wp; // Pretend it's assigned to a shared_ptr if (!wp.expired()) // Equivalent to use_count() != 0 { /* Here we're not 100% sure the raw pointer is accessible because a shared_ptr from another thread could hav

当您的ptr较弱时,您会:

std::weak_ptr<int> wp; // Pretend it's assigned to a shared_ptr
if (!wp.expired()) // Equivalent to use_count() != 0
{ /* Here we're not 100% sure the raw pointer is accessible because a shared_ptr from another thread
   could have been destroyed, and is in the process of decrementing the use_count from 1 to 0 and calling the deleter.*/

}
我不明白的是,根据文档,锁函数被定义为:

有效地返回
expired()?shared_ptr():shared_ptr(*this)
,以原子方式执行

因此,如果expired()(相当于use_count()==0)返回true,那么我们可以确定指针不能被取消引用,我们将返回一个空的共享\u ptr。另一方面,如果expired()返回false,我们将返回一个共享的ptr到资源,但问题是,正如我前面提到的,当expired()返回true时,我们知道指针坏了,但是当它返回false时,它可能是一个假负数,但我们将返回一个共享的ptr。当我们检查返回的shared_ptr时,另一个线程可能仍在写入控制块的过程中,对吗

当文档说“以原子方式执行”时,是否意味着每次要访问弱\u ptr时调用lock()方法都会使用互斥锁,还是使用原子操作?如果是的话,这项技术的性能成本是多少

我不认为它使用原子类型作为计数器,因为我听说了一个经常实施的技巧,我认为这是一种避免使用原子类型/操作的方法:

为所有共享的_ptr实例添加一个只是一种优化(保存) 复制/分配共享\u ptr时的一个原子增量/减量 实例)


相关的C++语言概念是排序。通常,一个操作在另一个操作之前或之后排序。在这种情况下,“原子执行”意味着在
expired()
之后不排序任何内容,而是在
shared\u ptr(*this)
之前排序

最后,这确实是一个编译器保证。实现的库知道如何让编译器做正确的事情。标准库中的锁是相似的;他们还必须确保编译器执行正确的操作。这实际上是由库作者来决定如何实现这两个功能


性能可能取决于实现,但这是一个非常常见的类。这意味着实现者会关心性能。

老实说,我不知道
弱的\u ptr::expired()
有什么好处。在多线程环境中,通过
shared_ptr
的最终强引用可以在另一个线程上发布,如果
expired()
返回true,您肯定知道该对象已被删除,但如果它返回
false
,则该对象的“有效性”在此期限内无效。除非您按照:
上的文档调用
lock()
,否则无法安全地假定任何内容。如果托管对象在线程之间共享,则此函数本质上是快速的。特别是,错误的结果可能在使用之前就过时了。真实的结果是可靠的
。最后的评论。我认为
expired
是Boost的一个保留,itt明确建议基本的
use\u count
功能是“仅用于调试和测试目的,而不是用于生产代码”。@selbie所以每次你想访问弱ptr资源时,你必须使用原子操作?lock()就是这样的吗?还是互斥?我甚至不知道有什么区别。@Zebrafish:什么是“必要的”或“不必要的”是什么。此外,你的问题到底是什么还不清楚。似乎你的问题是原子操作实际上是原子的,但更一般的怀疑是C++标准库对这种类型有任何线程保护。“它使用std::atomic还是std::mutex?”这是一个实现细节。操作是原子的;如何实现这一目标与你无关。
std::weak_ptr<int> wp; // Pretend it's assigned to a shared_ptr
if (wp.expired()) Equivalent to use_count() == 0
{ /* Here we are sure that the raw pointer is invalid because of the interesting property that once the use_count is 0 it can't get incremented anymore */

}
if (std::shared_ptr shp = wp.lock())
{// We know the resource is valid, we can use it
}