6

是否保证当 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)
}
4

1 回答 1

11

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

  • si下降到 0的引用计数
  • delete i被调用
  • 重生又si指向i

因此i重置后新分配的内存将指向未分配的内存,并且wi已正确过期(并且在si消失时会产生段错误,最终会再次尝试删除i)。

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

编辑后的答案:

这同样适用于那里:指针相同的事实与 shared_ptr 及其内部引用计数无关。用一个“邪恶”的例子可能会更清楚。这是错误的:

  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)。si1和(错误地)指向同一个内存的事实si2与 shared_ptr 和连接的weak_ptr 的生命周期无关。

指针的绝对值i不用于确定引用计数。对于 shared_ptr 和weak_ptr 两者。所以是的,这是有保证的!

事实上,当你需要一个对象的类内部的 shared_ptr 时,你需要enable_shared_from_this - 如果你使用shared_ptr(this)而不是shared_from_this ()你每次都会得到不同的 shared_ptr - 一旦它们中的第一个消失就销毁你的对象的参考计数。

于 2014-07-17T13:40:01.023 回答