Rei*_*ica 10 c++ destructor shared-ptr weak-ptr language-lawyer
我有一个std::shared_ptr自定义删除器和删除器,我想采取原始的临时副本std::shared_ptr.以代码形式表示:
struct Foo : public std::enable_shared_from_this<Foo>
{};
void deleter(Foo *f)
{
{
std::shared_ptr<Foo> tmp = f->shared_from_this(); // Line A
}
delete f;
}
int main()
{
std::shared_ptr<Foo> foo(new Foo, &deleter);
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:在A线上,可以说一下这个电话shared_from_this()吗?这合法吗?如果是这样,标准是否对其返回值有所说明?如果我们enable_shared_from_this用不同的weak_ptr或全局的引用替换foo,那么答案是否相同?
锵用的libc ++和GCC用的libstdc ++都产生代码终止对bad_weak_ptr例外,但我似乎无法为跟踪这一要求的标准.这是特定于实现的,还是我错过了规则?
我找到的所有相关规则(引用C++ 11):
20.7.2.2.2
shared_ptr析构函数1 ...如果
*this拥有一个对象p和一个删除器d,d(p)则称为
2 [ 注意: ......由于销毁会*this减少与*this一个共享所有权的实例数量,在*this销毁之后,所有shared_ptr共享所有权的实例*this将报告一个use_count()比前一个值少一个.- 尾注 ]20.7.2.2.5
shared_ptr观察员7
use_count返回:共享所有权的shared_ptr对象数,或者为空时为0 .*this*this*this
对我来说,似乎还不清楚是否use_count在删除器调用之前或之后发生了减量.获得bad_weak_ptr可靠的结果,还是仅仅未指定?
请注意,我故意避免像tmp我的示例代码中的指针将比删除器执行更长的情况.
Mas*_*nes 13
考虑
[c ++ 14-12.4-15]为对象调用析构函数后,该对象不再存在;
和
[C++ 14-20.8.2.4-7] shared_from_this()[...]需要:enable_shared_from_this应可访问的基类T的*这应是类型T的对象t的子对象须有在拥有&t的至少一个shared_ptr实例p.
因此,考虑到shared_ptr析构函数调用了删除器,在拥有它的最后一个shared_ptr的删除器中调用shared_from_this()会导致未定义的行为.
编辑:正如YSC所指出的,在C++ 17中, shared_from_this()需要表现为相应的weak_ptr转换调用.这会使问题变得复杂,因为不清楚weak_ptr :: expired()应该在删除器调用时返回...无论如何,20.7.2.2.2从字面上理解引用的注释,在这种情况下应该引发bad_weak_ptr.