C++ 当共享\u ptr重置为包含的相同地址时,是否保证弱\u ptr将过期?

C++ 当共享\u ptr重置为包含的相同地址时,是否保证弱\u ptr将过期?,c++,c++11,shared-ptr,weak-ptr,C++,C++11,Shared Ptr,Weak Ptr,当共享\u ptr重置为包含的相同地址时,是否保证弱\u 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() );

当共享\u ptr重置为包含的相同地址时,是否保证弱\u 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)
}

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

  • si
    的参考计数下降到0
  • 调用了删除i
  • 重生的
    si
    再次指向
    i
因此,重置后新分配的
i
将指向未分配的内存,并且
wi
已正确过期(当
si
消失时,将产生segfault,最终再次尝试删除
i

良好的实践是,在将裸指针分配给共享\u ptr后,永远不要引用该裸指针

编辑后回答:

同样的情况也适用于此:指针相同的事实与共享的\u 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
int*i=新的int;
std::共享ptr si1(i);
标准::共享_ptrsi2(i);//在销毁si2-boom时删除两次i!
标准:弱ptr wi1=si1;
si1.reset();
断言(wi1.expired());//真的
这与您的第一个示例类似(实际上是相同的):si1和si2是两个不同的共享_ptr(它们是重置前的si和重置后的si)。
si1
si2
(错误地)指向同一内存的事实与共享ptr和连接的弱ptr的寿命无关

i
指针的绝对值不用于确定参考计数。对于共享_ptr和弱_ptr。所以,是的,这是保证

事实上,当您需要一个对象的类内共享ptr时,如果您使用
shared\u ptr(this)
而不是每次都得到不同的共享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