【发布时间】:2018-03-20 16:42:08
【问题描述】:
我有一个带有自定义删除器的 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 的全局引用,答案会一样吗?
Clang 与 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被销毁后,与*this共享所有权的所有shared_ptr实例将 报告比其先前值小一的use_count()。 ——尾注]20.7.2.2.5
shared_ptr观察者7
use_count返回:shared_ptr对象的数量,包括*this,与*this共享所有权,或 0 当*this为空时。
对我来说,似乎不清楚use_count 的递减是发生在删除器调用之前还是之后。得到bad_weak_ptr 是一个可靠的结果,还是只是未指定?
请注意,我有意避免在我的示例代码中使用像 tmp 这样的指针会比删除器执行更有效的情况。
【问题讨论】:
-
I would like to take a temporary copy of the original std::shared_ptr0_0,为什么?! -
如果您不希望
tmp超出删除器的范围,为什么不使用原始指针Foo *f? -
@DavidHaim 关于接口管理、ABI 兼容性和虚拟基类之间转换的复杂框架的长篇故事,所有这些都建立在
shared_ptr之上。 -
@DanielTrugman 与我之前对 David Haim 的回复相同:遗留代码原因。
-
@Angew 相反,我会向 Foo 添加一些名为“move”的虚函数,它会移动指针的内容。如果删除器认为现在不是对象死亡的时间,它会移动它而不是增加引用计数
标签: c++ language-lawyer destructor shared-ptr weak-ptr