是否保证weak_ptr在shared_ptr重置为包含

Is it guaranteed that weak_ptr will expire when shared_ptr is reset to the same address that contains?

本文关键字:ptr 包含 shared weak 是否      更新时间:2023-10-16

是否保证当shared_ptr重置为包含的相同地址时weak_ptr将过期?

#include <cassert>
#include <memory>
int main()
{
    int* i = new int(0);
    std::shared_ptr<int> si( i );
    std::weak_ptr<int> wi = si;
    si.reset( i );
    assert( wi.expired() ); // wi.expired() == true (GCC 4.7)
}

或者当wi.expired()的值没有定义时是这种情况?

编辑:

我现在稍微修改一下这个问题:

shared_ptr被重置到与weak_ptr初始化时包含shared_ptr的相同地址时,是否保证weak_ptr将过期?

#include <cassert>
#include <memory>
int main()
{
    int* i = new int(0);
    std::shared_ptr<int> si( i );
    std::weak_ptr<int> wi = si;
    si.reset();
    int* j = new int(0); 
    // Suppose that new returns the same address that contains variable i :  
    assert(j == i); 
    si.reset( j );
    assert( wi.expired() ); // wi.expired() == true (GCC 4.7)
}

一方面,它实际上应该。另一方面,将同一个指针分配给两个不同的共享指针(si-before-reset和si-after-reset)是不正确的。实际上,调用si.reset(i)会发生以下情况:

  • si的ref_count降为0
  • delete i被调用
  • 重生的si再次指向i

所以重置后新分配的i将指向未分配的内存,并且wi正确过期(并且当si消失时将导致段故障,最终试图再次删除i)。

最好的做法是永远不要在裸指针被分配给shared_ptr后引用它。

编辑后的回答:

同样适用于这里:指针相同的事实与shared_ptr及其内部ref_count无关。用一个"邪恶"的例子也许更清楚。这是错误的:

  int *i = new int;
  std::shared_ptr<int> si1(i);
  std::shared_ptr<int> si2(i); // deleting twice i on destruction of si2 - boom!
  std::weak_ptr<int> wi1 = si1;
  si1.reset();
  assert (wi1.expired());      // true

这与您的第一个示例类似(实际上相同):si1和si2是两个不同的shared_ptr(它们是si-before-reset和si-after-reset)。si1si2(错误地)指向相同的内存与shared_ptr和连接的weak_ptr的寿命无关。

i指针的绝对值不用于确定ref-count。shared_ptr's和weak_ptr's。所以,是的,这是有保证的!

事实上,当你需要一个对象的shared_ptr从它的类内部,你需要enable_shared_from_this -如果你使用shared_ptr(this)而不是shared_from_this()你得到不同的shared_ptr的每次-销毁你的对象一旦第一个已经超出ref-counts