考虑下面的代码:
#include <memory>
#include <iostream>
using namespace std;
struct MySharedStruct
{
int i;
};
void print_value_of_i(weak_ptr<MySharedStruct> weakPtr)
{
if (shared_ptr<MySharedStruct> sp = weakPtr.lock())
{ cout << "Value of i = " << sp->i << endl; }
else
{ cout << "Resource has expired"; }
}
int main()
{
shared_ptr<MySharedStruct> sharedPtr(new MySharedStruct() );
sharedPtr->i = 5;
weak_ptr<MySharedStruct> weakPtr;
weakPtr = sharedPtr;
print_value_of_i(weakPtr);
sharedPtr.reset(new MySharedStruct() ); // <<----- How does weak_ptr know it has expired after this line executes?
sharedPtr->i = 10;
print_value_of_i(weakPtr);
return 0;
}
请问该怎么做weak_ptr
知道它已过期考虑到资源shared_ptr
是引用已经基本上是由另一个资源替代? 什么weak_ptr
跟踪就知道肯定是旧共享资源被破坏和新的共享资源取代? 的方法,例如实施例定义(如果相关的话) lock
在weak_ptr
将不胜感激。
当所分配的控制块shared_ptr
从一个普通的指针创建包含用于对象和两个基准计数器的指针对象本身和定制删除对象(如有)。 当参考计数器达到零的对象被释放,并且将指针设置为空。 所以,当对象的引用计数为零,这意味着该物体消失。
对于x86和x86-64他们使用原子操作,并没有明确的锁定(无互斥体或自旋锁)。 实施的关键是功能的特殊无锁(繁忙的旋代码语言) atomic_conditional_increment
仅如果不是零递增对象引用计数器。 它在实现中使用weak_ptr::lock
功能,以应付比赛时,多个线程试图创建一个shared_ptr
来自同一weak_ptr
使用对象的引用计数为零。 见http://www.boost.org/doc/libs/1_52_0/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp
控制块本身之间共享shared_ptr
的和weak_ptr
的和为自己的另一个参考计数器,以便直到它的最后一个引用被释放它保持活着。
当shared_ptr
被重新分配它指向另一个控制块,使得一个控制块只有永远指向一个相同的对象。 换句话说,没有替换一个对象与另一个在控制块。
简答
我怀疑大多数实现通过具有共享控制块既实现这一weakPtr
和sharedPtr
参考。 当sharedPtr
复位时,它递减一个use_count
,所述控制块weakPtr
可以使用以测试是否指针是有效的。
长一点的回答
但我认为,可以根据具体实现而变化。 这里有一个窜吹的C ++ 11个标准应该发生的事情说:
shared_ptr<MySharedStruct> sharedPtr(new MySharedStruct());
每20.7.2.2.1, sharedPtr
构造与给定数据的所有权。
weak_ptr<MySharedStruct> weakPtr;
weakPtr = sharedPtr;
每20.7.2.3.1, weakPtr
被构造和然后被分配的值sharedPtr
。 转让后, weakPtr
和sharedPtr
现在分享给定数据的所有权。
sharedPtr.reset(new MySharedStruct());
每20.7.2.2.4, reset(Y*)
等价于shared_ptr(Y*).swap(*this)
。 换句话说, sharedPtr
交换与临时内容shared_ptr
拥有新的数据。
在交换之后, sharedPtr
将拥有新的数据,并临时将共享旧的数据与所有权weakPtr
。
每20.7.2.2.2,临时然后破坏:
- 由于临时拥有旧数据和不共享与其他所有权
shared_ptr
实例,它删除旧数据。 - 共享与临时所有权所有实例
shared_ptr
将报告use_count()
比其先前的值减一。
这意味着, weakPtr.use_count() == 0
。
if (shared_ptr<MySharedStruct> sp = weakPtr.lock()) {
cout << "Value of i = " << sp->i << endl;
} else {
cout << "Resource has expired";
}
每20.7.2.3.5,呼吁lock
相当于
expired() ? shared_ptr<T>() : shared_ptr<T>(*this)
...和expired()
相当于
use_count() == 0
...这意味着lock
会返回一个空shared_ptr
。