[英]`weak_ptr::expired` behavior in the dtor of the object
请考虑以下代码:
#include <iostream>
#include <memory>
using namespace std;
class T;
std::weak_ptr<T> wptr;
class T
{
public:
T() { }
~T() {
std::cout << "in dtor" << std::endl;
std::cout << (wptr.expired() ? "expired" : "not expired") << std::endl;
}
};
int main() {
{
auto ptr = std::make_shared<T>();
wptr = ptr;
std::cout << (wptr.expired() ? "expired" : "not expired") << std::endl;
}
return 0;
}
在这段代码中,我试图找出weak_ptr
在对象销毁阶段是否过期。 看来是这样。 输出是:
not expired
in dtor
expired
我用gcc-5.1和ideone 。
现在,我有另一个问题。 我找不到任何文档说明这是标准行为。 难道是保证这样的工作方式, 始终 ?
现在,我有另一个问题。 我找不到任何文档说明这是标准行为。 难道是保证这样的工作方式, 始终 ?
没有。事实上,正如LWG第2751号提出的那样,它在标准中没有明确规定 。
C ++ 14标准不包含任何语言,该语言保证
shared_ptr
运行的删除器将所有关联的weak_ptr
实例视为已过期。 例如,标准似乎不保证以下代码段中的断言不会触发:std::weak_ptr<Foo> weak; std::shared_ptr<Foo> strong{ new Foo, [&weak] (Foo* f) { assert(weak.expired()); delete f; }, }; weak = strong; strong.reset();
似乎很清楚,意图是相关的
weak_ptr
已过期,因为否则shared_ptr
删除器可以恢复对正被删除的对象的引用。建议的修复:23.11.3.2 [util.smartptr.shared.dest]应指定在调用删除器或调用
delete p
之前对析构函数引起的use_count()
减少进行use_count()
。
上面链接的~shared_ptr()
的当前措辞仅表示调用了删除器,并且非规范性地说明共享所有权的实例数量减少了。
虽然在调用删除器时意图可能是weak.expired()
,但依赖于此是有问题的。 确实有理由相信, shared_ptr
在被销毁后不再拥有所有权 - 在破坏期间询问这个问题有点奇怪。
像这样使用make_shared将使用您提供的默认构造函数创建一个对象。
template< class T, class... Args >
shared_ptr<T> make_shared( Args&&... args );
构造一个T类型的对象,并使用args作为T的构造函数的参数列表将其包装在
std::shared_ptr
中。该对象的构造就像表达式一样( std :: make_shared )
在主要的匿名范围之后。 共享的ptr将被删除。
当发生以下任一情况时,对象将被销毁并释放其内存:
拥有该对象的最后剩余的shared_ptr被销毁; ( std :: shared_ptr )
。
shared_ptr的析构函数减少控制块的共享所有者的数量。 如果该计数器达到零,则控制块将调用托管对象的析构函数。 在std :: weak_ptr计数器也达到零之前,控制块不会解除分配。 std :: shared_ptr实施说明
这意味着您的对象将在最后一个共享ptr的破坏开始后调用其析构函数。 输出:
not expired
in dtor
expired
是预期的行为。
不是标准本身,但是:
http://en.cppreference.com/w/cpp/memory/weak_ptr/expired
检查托管对象是否已被删除。 相当于use_count()== 0。
因此,在删除之前或之后,天气use_count
被设置为0成为问题。 现在标准草案中没有这个内容: http : //www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3690.pdf [第566页20.9.2.2.2]
~shared_ptr()
;功效:
- 如果
*this
为空或与另一个shared_ptr
实例共享所有权(use_count()> 1),则没有副作用。- 否则,如果
*this
拥有对象p
和删除器d
,则调用d(p)
。- 否则,
*this
拥有一个指针p
,并调用delete p
。[注意:由于
*this
的销毁会减少与*this
共享所有权的实例数量,在*this
已销毁之后,所有与*this
共享所有权的shared_ptr
实例将报告比其更少的use_count()
以前的价值。 - 结束说明]
当没有更多shared_ptr
引用该对象时, weak_ptr
到期。
当(紧接着)最后一个shared_ptr
停止引用它被销毁的对象时。
此时没有shared_ptr
引用它,因此任何weak_ptr
都已过期。
现在调用对象的析构函数,如果它具有单独的存储(即不是使用make_shared
创建),则会释放其存储。
存储引用计数和原始指针以及删除功能的控制块在存在任何指向它的weak_ptr
仍然存在。 当最后一个weak_ptr
停止引用它时,控制块也被销毁并解除分配。 即, shared_ptr
实例使对象本身及其控制块保持活动,而weak_ptr
实例使控制块保持活动状态。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.