我有一个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);
}
我的问题是:在线 A ,可以说一下shared_from_this()
的电话吗?这合法吗?如果是这样,标准是否对其返回值有所说明?如果我们将enable_shared_from_this
替换为weak_ptr
或foo
的全局引用,答案是否相同?
bad_weak_ptr
异常的代码,但我似乎无法将此跟踪为 required 按标准。这是特定于实现的,还是我错过了规则?
我找到的所有相关规则(引用C ++ 11):
20.7.2.2.2
shared_ptr
析构函数1 ...如果
*this
拥有对象p
和删除者d
,则d(p)
被称为
2 [注意: ...由于*this
的销毁会减少与*this
共享所有权的实例数量 一,在*this
被销毁后,与shared_ptr
共享所有权的所有*this
个实例都将被删除 报告的use_count()
比之前的值少一个。 -end note ]20.7.2.2.5
shared_ptr
观察员7
use_count
返回:shared_ptr
个对象的数量,包括*this
,与*this
共享所有权,或0 当*this
为空时。
对我来说,似乎不清楚use_count
的减少是在发生删除之前还是之后发生的。获得bad_weak_ptr
可靠的结果,还是仅仅是未指定?
请注意,我故意避免在我的示例代码中像tmp
这样的指针比删除器执行更久的情况。
答案 0 :(得分:13)
考虑
[c ++ 14-12.4-15]为对象调用析构函数后,该对象不再存在;
和
[c ++ 14-20.8.2.4-7] shared_from_this ()[...]要求:enable_shared_from_this应该是T的可访问基类。*这应该是一个子对象类型为T的对象t 至少应有一个拥有&amp; t 的shared_ptr实例。
所以,考虑到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。