请考虑以下代码:
#include#include using namespace std; class T; std::weak_ptr 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 (); wptr = ptr; std::cout << (wptr.expired() ? "expired" : "not expired") << std::endl; } return 0; }
在这段代码中,我试图找出weak_ptr
s在对象销毁阶段是否过期.看来是这样.输出是:
not expired in dtor expired
我用gcc-5.1和ideone.
现在,我有另一个问题.我找不到任何文档说明这是标准行为.难道是保证这样的工作方式,始终?
现在,我有另一个问题.我找不到任何文档说明这是标准行为.难道是保证这样的工作方式,始终?
实际上,正如LWG第2751号提出的那样,它在标准中没有明确规定.
C++ 14标准不包含任何语言,该语言保证由a运行的删除器
shared_ptr
将所有关联的weak_ptr
实例视为已过期.例如,标准似乎不保证以下代码段中的断言不会触发:std::weak_ptrweak; std::shared_ptr strong{ new Foo, [&weak] (Foo* f) { assert(weak.expired()); delete f; }, }; weak = strong; strong.reset(); 似乎很清楚,意图是关联的
weak_ptr
s已过期,因为否则shared_ptr
删除者可以恢复对正被删除的对象的引用.建议修复:23.11.3.2 [util.smartptr.shared.dest]应指定
use_count()
在调用删除器或调用之前对析构函数引起的减少进行排序delete p
.
~shared_ptr()
上面链接的当前措辞仅表示调用删除器,非规范性说明共享所有权的实例数量减少.
虽然意图可能是weak.expired()
在调用删除器时,依赖于此是有问题的.shared_ptr
确切地说,在它被摧毁之后不再拥有所有权是真的是合理的 - 在破坏期间询问这个问题有点奇怪.
像这样使用make_shared将使用您提供的默认构造函数创建一个对象.
template< class T, class... Args > shared_ptrmake_shared( Args&&... args );
构造一个T类型的对象,并将其包装在一个
std::shared_ptr
using args中作为T的构造函数的参数列表.该对象就像表达式一样构造(std :: make_shared)
在主要的匿名范围之后.共享的ptr将被删除.
当发生以下任一情况时,对象将被销毁并释放其内存:
拥有该对象的最后剩余的shared_ptr被销毁; (std :: shared_ptr)
.
shared_ptr的析构函数减少控制块的共享所有者的数量.如果该计数器达到零,则控制块将调用托管对象的析构函数.在std :: weak_ptr计数器也达到零之前,控制块不会解除分配.std :: shared_ptr实施说明
这意味着您的对象将在最后一个共享ptr的破坏开始后调用其析构函数.输出:
not expired in dtor expired
是预期的行为.