当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
的引用计数下降到 0delete 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 - 一旦它们中的第一个超出引用计数就销毁你的对象。
关于c++ - 当 shared_ptr 重置为包含的相同地址时,是否保证 weak_ptr 会过期?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24805006/