shared_ptr问题从成员函数返回上传版本

M2t*_*2tM 3 c++ this shared-ptr c++11

我最近一直在尝试使用shared_ptr,而且我遇到了一些奇怪的情况.我想要的是一个模板成员函数,它能够返回其派生类型的shared_ptr.我正在运行visual studio 2010,它可以访问一些新的c ++ 0x标准,但我认为boost shared_ptr的行为类似.

这很好用的指针.我刚刚返回了一个dynamic_cast <DerivedClass*>(这个).但是,我有点难过,因为即使使用enable_shared_from_this,对象也会在调用函数后尝试删除自身(这很糟糕).我可能正在接近这个错误,但我想弄清楚如何模拟以下的裸指针等效(这是有效的)(这是我遇到问题的代码).

//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());
  }
}
Run Code Online (Sandbox Code Playgroud)

编辑:似乎功能正常,问题在于我如何使用它.这很糟糕,例如执行以下操作:

std::shared_ptr<DerivedClass> p = std::make_shared<DerivedClass>();
p->getType<DerivedClass>->someOtherFunctionOnlyInTheDerivedClass();
Run Code Online (Sandbox Code Playgroud)

这不是问题:

std::shared_ptr<BaseClass> p = std::make_shared<DerivedClass>();
p->getType<DerivedClass>->someOtherFunctionOnlyInTheDerivedClass();
Run Code Online (Sandbox Code Playgroud)

我不完全确定转换为相同类型或引用计数问题是否存在问题.在任何情况下,我都做了一些愚蠢的事情并且它已经破坏了,避免了那时不必要的getType调用似乎在我使用它的其他每种情况下都能正常工作.也许有人可以准确地解释是什么原因导致第一个例子与第二个例子一起工作.我会为那个答案分配点数.

Nat*_*nst 5

为了扩展Stuart的答案并(可能)解释你崩溃的原因,我最好的猜测是你正在调用getType一个stack-alloc'd实例.这是使用的一个主要缺陷enable_shared_from_this.

#include <memory>

class Base : public std::enable_shared_from_this<Base>
{
public:
    virtual ~Base() {}

    template <typename D>
    std::shared_ptr<D> getType()
    {
        return std::dynamic_pointer_cast<D>(shared_from_this());
    }
};

class Derived : public Base
{
public:
    void f() {}
};

int main()
{
    std::shared_ptr<Derived> d = std::make_shared<Derived>();
    d->getType<Derived>()->f(); // fine

    Derived d2;
    Base* p = &d2;
    p->getType<Derived()>->f(); // will attempt to delete d2 after f() returns.

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

发生这种情况的原因是因为d2当它在堆栈上时引用计数为零.调用shared_from_this返回a shared_ptr将引用计数增加到1.一旦该指针超出范围,它将其计数减少到零,然后尝试删除实例,当然,该实例位于堆栈上.

我能想到保护自己的唯一方法,就是让所有构造函数都受到保护或私有,并提供动态分配任何实例的静态函数,shared_ptr当然,返回s.