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

时间:2014-07-17 13:32:08

标签: c++ c++11 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( i );

    assert( wi.expired() ); // wi.expired() == true (GCC 4.7)
}

或者,如果未定义wi.expired()的值,是这种情况吗?

修改

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

weak_ptr重置为同一地址时保证shared_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)
}

1 个答案:

答案 0 :(得分:11)

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

  • si的重新计数降至0
  • delete i已被调用
  • 重生的si再次指向i

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

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

编辑后的答案:

同样适用:指针相同的事实与shared_ptr及其内部引用计数无关。对于邪恶的&#34;这可能更清楚。例。这是错的:

  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指针的绝对值不用于确定引用计数。对于shared_ptr和weak_ptr都是如此。是的,这是有保证的!

事实上,当你需要来自其类中的对象的shared_ptr时,你需要enable_shared_from_this - 如果你使用的是shared_ptr(this)而不是shared_from_this(),那么你会得到不同的shared_ptr&#39每次都是 - 一旦他们的第一个人退出重新计数就摧毁你的物体。