C++11 检查共享ptr的唯一所有权
我经常想检查C++11 检查共享ptr的唯一所有权,c++11,thread-safety,smart-pointers,race-condition,C++11,Thread Safety,Smart Pointers,Race Condition,我经常想检查共享\u ptr是否是共享对象的唯一所有者。在销毁最后一个共享的\u ptr之前,可以方便地传递行为,而不必在销毁之后进行操作(我的特定用例是通过在销毁之前使用另一个shared\u ptr来保存弱指针。在销毁开始之后,要挽救它们已经太晚了) C++11[草案]20.7.2.1.4: 为了确定是否存在数据竞争,成员 功能应仅访问和修改共享ptr和弱ptr 对象本身,而不是它们所引用的对象。变化 use_count()不反映可能引入数据的修改 比赛 澄清了我对p的担忧。使用_count
共享\u ptr
是否是共享对象的唯一所有者。在销毁最后一个共享的\u ptr之前,可以方便地传递行为,而不必在销毁之后进行操作(我的特定用例是通过在销毁之前使用另一个shared\u ptr
来保存弱指针。在销毁开始之后,要挽救它们已经太晚了)
C++11[草案]20.7.2.1.4:
为了确定是否存在数据竞争,成员
功能应仅访问和修改共享ptr和弱ptr
对象本身,而不是它们所引用的对象。变化
use_count()不反映可能引入数据的修改
比赛
澄清了我对p的担忧。使用_count()==1
导致数据竞争。然而,我仍然不相信以我想要的方式使用它是安全的
在单线程世界中,如果use\u count()
返回1,则您知道您是该对象的最后所有者。在一个避免数据竞争的多线程世界中,use\u count()
为1就足以确保您是唯一的所有者,这似乎是合理的,但我在试图从规范中获得这一点时遇到了挫折。我不知道是否存在允许使用计数为1的漏洞,即使另一个线程上存在另一个共享的ptr。另一方面,use\u count
的定义可能会变为goo,这似乎令人沮丧,因为我将共享的ptr交给了另一个线程
如果use\u count()
为1,但根据规范的规则,我不是唯一的所有者,我会遇到这种情况吗?我认识到,由于种族的原因,2的use\u count
并不明确表示我在共享(在我调用use\u count
这个线程后,另一个线程可能会释放我的对象),但一旦我看到1的use\u count
,我就对另一个方向感兴趣了
作为第二个相关问题:相同的规则是否适用于unique
,它似乎是根据我想要的实现定制的,但没有关于线程安全的任何额外声明
Edit:作为对我得到的答案的回应,我感兴趣的情况是我们调用的
unique\u count
只能由单个线程访问,因此我不必担心任何其他线程成功复制它。。。他们必须找到自己的共享\u ptr
才能复制 当然。即使指定use\u count()
和unique()
都是原子的,但它不会:
long use_count()const noexcept代码>
返回:与*this
共享所有权的共享\u ptr
对象(包括*this
)的数量,或0
当*此
为空时。
[注意:use\u count()
不一定有效。-结束注意]
bool unique()const noexcept代码>
返回:use_count()==1
[注意:unique()
写入时,当get()==nullptr
-结束注释]
没有什么可以阻止这样的事情发生:
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 :-( */ /**/
} /**/
std::shared_ptr sp;
//线程1//线程2
bool uniq=sp.unique()/**/
/**/std::shared_ptr cpy=sp;
if(uniq){/**/
/*我的???*/**/cpy->foo();
/*否:-(*//**/
} /**/
如果存在指向与单个共享\u ptr
相同控制块的弱\u ptr
存在的可能性,并且如果另一个线程可能将该弱\u ptr
转换为共享\u ptr
,则您的线程可以观察到使用\u count()==1,但当它可以利用该信息做任何事情时,另一个线程可以从弱ptr
构造一个新的共享ptr
,将使用计数增加到2
即使没有弱\u ptr
s,如果有多个线程具有对您的共享\u ptr
的读取权限(例如,假设它是全局的),那么在您观察use_count()==1
后,另一个线程可能会复制它
如果任何其他线程都无法访问您的shared_ptr
,并且其他线程不可能将弱_ptr
转换为共享_ptr
,则使用_count()==1
是可以安全依赖的。请注意,您不需要另一个线程来复制将要发布的共享ptr
,但另一个线程复制共享ptr
或从弱ptr
创建一个共享ptr
就足够了,它与您要发布的共享ptr
共享所有权即将发布。正如您所说,有weak\u ptr
s存在,因此@Barry指出use\u count
可能返回1是正确的,但在看到值后,另一个线程可能使用weak\u ptr
创建了另一个引用。