从成员函数返回向上转换版本的shared_ptr问题
我最近一直在尝试shared_ptr,并且遇到了一些奇怪的情况。我想要的是一个模板成员函数,它能够返回其派生类型的shared_ptr。我正在运行 Visual Studio 2010,它可以访问一些新的 C++0x 标准,但我认为 boost Shared_ptr 的行为类似。
这对于裸指针来说效果很好。我刚刚返回了一个dynamic_cast
//assume we have a virtual function as well.
class BaseClass : public std::enable_shared_from_this<BaseClass>
{
....
template<typename DerivedClass>
std::shared_ptr<DerivedClass> BaseClass::getThis(){
//I had some assert code here to ensure typeid matched
return std::dynamic_pointer_cast<DerivedClass>(shared_from_this());
}
}
编辑:看起来该功能工作正常,问题在于我如何使用它。例如,执行以下操作是不好的:
std::shared_ptr<DerivedClass> p = std::make_shared<DerivedClass>();
p->getType<DerivedClass>->someOtherFunctionOnlyInTheDerivedClass();
这不是问题:
std::shared_ptr<BaseClass> p = std::make_shared<DerivedClass>();
p->getType<DerivedClass>->someOtherFunctionOnlyInTheDerivedClass();
我不完全确定这是转换为相同类型的问题,还是引用计数问题。无论如何,我做了一些愚蠢的事情并且它坏了,避免不必要的 getType 调用在这一点上似乎在我使用它的所有其他情况下都工作得很好。也许有人可以准确解释是什么原因导致第一个示例崩溃而第二个示例正常工作。我会给这个答案打分。
I've recently been trying out shared_ptr and I've run across a bit of a weird case. What I want is a template member function which is capable of returning a shared_ptr of its derived type. I'm running visual studio 2010 which has access to some of the new c++0x standard, but I assume the boost shared_ptr behaves similarly.
This worked fine with bare pointers. I just returned a dynamic_cast<DerivedClass*>(this). I'm kind of stumped here, however, because even using enable_shared_from_this the object attempts to delete itself after the function is called (which is bad). I am probably approaching this wrong, but I'd like to work out how to simulate the bare pointer equivalent (which was working) of the following (this is the code I'm having trouble with).
//assume we have a virtual function as well.
class BaseClass : public std::enable_shared_from_this<BaseClass>
{
....
template<typename DerivedClass>
std::shared_ptr<DerivedClass> BaseClass::getThis(){
//I had some assert code here to ensure typeid matched
return std::dynamic_pointer_cast<DerivedClass>(shared_from_this());
}
}
edit: It seems the function works correctly, the problem was with how I was using it. It is bad, for example to do the following:
std::shared_ptr<DerivedClass> p = std::make_shared<DerivedClass>();
p->getType<DerivedClass>->someOtherFunctionOnlyInTheDerivedClass();
This is not a problem:
std::shared_ptr<BaseClass> p = std::make_shared<DerivedClass>();
p->getType<DerivedClass>->someOtherFunctionOnlyInTheDerivedClass();
I'm not entirely sure if it's a problem with converting to the same type, or a reference counting issue. In any case, I was doing something dumb and it broke, avoiding the unnecessary getType call at that point seems to work fine in every other case I am using it. Maybe someone can explain precisely what causes the first example to break with the second example working. I'll assign points to that answer.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
为了扩展 Stuart 的答案并(可能)解释您崩溃的原因,我最好的猜测是您在堆栈分配的实例上调用
getType
。这是使用enable_shared_from_this
的一个主要陷阱。发生这种情况的原因是
d2
在堆栈上时的引用计数为零。调用shared_from_this
返回一个shared_ptr
,它将引用计数增加到 1。一旦该指针超出范围,它就会将其计数减少到零,然后尝试删除该实例,当然,该实例位于堆栈上。我能想到的保护自己免受这种情况影响的唯一方法是,将所有构造函数设为受保护或私有,并提供动态分配任何实例的静态函数,返回shared_ptr,课程。
To expand on Stuart's answer and to (possibly) explain why you were crashing, my best guess is that you were calling
getType
on a stack-alloc'd instance. It's a major pitfall to usingenable_shared_from_this
.The reason this occurs is because the reference count of
d2
is zero when it's on the stack. Callingshared_from_this
returns ashared_ptr
that increments the reference count to one. Once this pointer goes out of scope, it decrements its count to zero, which then attempts to delete the instance, which, of course, is on the stack.The only way that I can think of protecting yourself from this, off the top of my head, is to make all constructors protected or private and provide static functions that dynamically allocate any instances, returning
shared_ptr
s, of course.就其价值而言,我没有遇到您通过以下最小可编译示例描述的问题(看起来像您上面描述的代码):
这对您来说会崩溃吗?
For what it's worth, I don't experience the problem you're describing with the following minimal compileable example (which looks like the code you describe above):
Does this crash for you?