我经常希望检查shared_ptr
是否是共享对象的唯一所有者。在销毁最后一个shared_ptr之前交换行为会很方便,而不是在销毁之后不得不这样做(我的特定用例是在破坏之前通过用另一个shared_ptr
拯救弱指针来处理保存弱指针。已经开始,拯救他们已经太晚了。)
C ++ 11 [draft] 20.7.2.1.4:
为了确定数据竞争的存在,成员 函数只能访问和修改shared_ptr和weak_ptr 对象本身而不是它们引用的对象。改变在 use_count()不反映可以引入数据的修改 比赛。
This question澄清了我对p.use_count() == 1
导致数据竞争的担忧。但是,我仍然不相信以我想要的方式使用它是安全的。
在单线程世界中,如果use_count()
返回1,那么您就知道您是该对象的最后一个所有者。在一个你已经避免数据竞争的多线程世界中,use_count()
的1足以确保你是唯一的所有者似乎是合理的,但我有一个令人沮丧的时间试图从特别的。我无法判断是否存在允许use_count为1的漏洞,即使另一个线程上存在另一个shared_ptr。另一方面,似乎令人沮丧的是use_count
的定义可能会变成goo,因为我将shared_ptr交给了另一个线程。
我是否可以进入use_count()
为1的情况,但根据规范的规则,我不是唯一的所有者?我认识到,由于比赛,一个use_count
的2并没有明确表示我正在分享(另一个线程可能在我在此线程上调用use_count
之后释放我的对象),但我'一旦我看到use_count
的1,我就对另一个方向感兴趣。
作为第二个相关问题:同样的规则是否适用于unique
,这似乎是根据我想要的实现量身定制的,但是没有关于线程安全的任何额外声明?
修改:为了回答我已经得到的答案,我感兴趣的情况是shared_ptr
我们打电话unique_count
只能通过单线程,所以我不必担心任何其他线程成功复制它...他们必须找到自己的shared_ptr
来复制!
答案 0 :(得分:3)
如果存在weak_ptr
存在与单个shared_ptr
相同的控制块,并且另一个线程可能将weak_ptr
转换为shared_ptr
的可能性然后你的线程可以观察use_count() == 1
,但是当它可以对该信息做任何事情时,另一个线程可以从shared_ptr
构造一个新的weak_ptr
,撞击use_count
1}}最多2个。
即使没有weak_ptr
s,如果多个线程对shared_ptr
具有读访问权限(例如说它是全局的),那么另一个线程可能会在您观察之后复制它use_count() == 1
。
如果任何其他线程无法访问您的shared_ptr
,并且其他线程不可能将weak_ptr
转换为shared_ptr
,则use_count() == 1
是安全的依靠。
答案 1 :(得分:0)
绝对。即使指定use_count()
和unique()
都是原子的,也不是:
long use_count() const noexcept;
返回:shared_ptr
个对象的数量,包括*this
,与*this
共享所有权,或0 当*this
为空时。
[注意:use_count()
不一定有效。 -end note]
bool unique() const noexcept;
返回:use_count() == 1
。
[注意:unique()
可能比use_count()
更快。如果您使用unique()
来实现副本 写,不要在get() == nullptr
时依赖特定值。 -end note]
没有什么可以阻止这样的事情发生:
std::shared_ptr<Foo> sp;
// thread 1 // thread 2
bool uniq = sp.unique(); /**/
/**/ std::shared_ptr<Foo> cpy = sp;
if (uniq) { /**/
/* mine?? */ /**/ cpy->foo();
/* nope :-( */ /**/
} /**/