我有一个功能,需要一个shared_ptr<MyClass>.在某些成员函数memfun中MyClass,我需要传递this给该函数.但如果我写
void MyClass:memfun()
{
func(shared_ptr<MyClass>(this))
}
Run Code Online (Sandbox Code Playgroud)
我假设在呼叫结束后,引用计数将达到0并且this将被尝试销毁,这是不好的.
然后我记得那个类enable_shared_from_this有这个功能shared_from_this.
所以现在我将使用以下内容:
class MyClass: public enable_shared_from_this<MyClass>
{
void MyClass:memfun()
{
func(shared_from_this());
}
};
Run Code Online (Sandbox Code Playgroud)
问题是:
1)绝对不可能在不衍生的情况下使用该功能enable_shared_from_this吗?
2)是否enable_shared_from_this意味着在具有自动存储持续时间的对象上调用memfun会导致不好的事情?例如
int main()
{
MyClass m; //is this OK?
m.memfun(); // what about this?
}
Run Code Online (Sandbox Code Playgroud)
3)如果我从MyClass派生,是否会正确继承enable_shared_from_this功能,还是需要再次派生?那是,
class MyCoolClass: public Myclass
{
void someCoolMember
{
someCoolFuncTakingSharedPtrToMyCoolClass(shared_from_this());
}
}
Run Code Online (Sandbox Code Playgroud)
这个可以吗?或者正确如下?
class MyCoolClass: public Myclass, public enable_shared_from_this<MyCoolClass>
{
void someCoolMember
{
someCoolFuncTakingSharedPtrToMyCoolClass(enable_shared_from_this<MyCoolClass>::shared_from_this());
}
}
Run Code Online (Sandbox Code Playgroud)
首先十分感谢.
Ant*_*ams 26
1)这取决于你的意思是"做这个"你是否可以.您始终可以shared_ptr从原始指针构造一个this,但不会与另一个shared_ptr从原始指针单独构造的实例共享引用计数.因此,您需要在一个或其他实例上使用自定义删除器以避免双重删除,但除非您非常小心,否则shared_ptr由于对象被删除,但仍可从另一个实例访问,最终可能会出现悬空实例.
shared_from_this使您能够保证,如果您shared_ptr的对象有一个实例,那么您可以构建另一个实例而不复制第一个实例,并且这些实例将共享引用计数.您可以通过将a weak_ptr作为类成员存储,并在第一次shared_ptr为对象分配时设置该值来实现此目的.
2)调用shared_from_this()要求至少有一个shared_ptr实例已指向您的对象.如果你在没有shared_ptr自定义删除器实例的自动对象上使用它,那么你会发生坏事.
3)如果你派生自你的类,那么该enable_shared_from_this功能将为你提供一个shared_ptr基类(派生自的类enable_shared_from_this).然后,您可以使用static_pointer_cast或dynamic_pointer_cast将结果shared_from_this()转换为指向派生类的指针.
Dav*_*eas 11
这里的重要问题是为什么函数通过a来获取参数shared_ptr.它是否在内部存储指针以供以后使用?它是否仅在通话期间使用它?为什么所有权在呼叫者和被呼叫者之间被稀释?
一些答案表明,如果要将堆栈分配的对象传递给函数,则提供无操作删除器,但如果该函数实际存储以shared_ptr供以后使用,则可能是这样的情况,当它到达时它,本地分配的对象不再在堆栈中,您触发UB.拥有no-op删除器shared_ptr将允许调用,但语义将不正确.
如果该函数未存储以shared_ptr供以后使用,那么导致该API的设计决策是什么?如果您可以更改函数(并且没有迫在眉睫的原因),请让它通过引用接收参数,并且您将拥有一个友好的界面,不会shared_ptr无缘无故地强加.
如果最后您确定可以保证堆栈中的对象在该函数调用触发的整个过程中保持活动状态,那么只能使用no-op deleter.