非侵入式智能指针在继承和多重继承方面的表现如何?

时间:2010-10-13 15:34:13

标签: visual-studio-2010 c++11 smart-pointers

我正在使用C ++。使用Visual Studio 2010的C ++ 0x是正确的。

假设我有一个Z类。为了让我的应用程序更安全地使用指向这个类的指针,我可以一直使用智能指针(共享指针,弱指针)。

现在这个类Z继承自类X.我的应用程序的某些部分将使用指向类X的指针,其他部分将使用指向类Z的指针。

  • 我还可以使用智能指针吗?
  • 如果我有一些引用X而其他引用Z的共享指针仍然有效吗?是否保证销毁实例的最后一个共享指针(无论是std::shared_ptr<X>还是std::shared_ptr<Z>)是否会删除实例?我确定如果删除std::shared_ptr<X>,只要还有另一个std::shared_ptr<Y>,该实例就会保留吗?

现在假设我使用多重继承,其中Z继承自类X和Y. 我的应用程序的某些部分适用于std::shared_ptr<X>,其他部分适用std::shared_ptr<Y>,其他部分适用std::shared_ptr<Z>

  • 我还能以这种方式使用共享指针吗?
  • 是否仍然保证只有最后一个智能指针(无论是指向X,Y还是Z)都会删除实例?

顺便说一句,我怎样才能安全地将一个智能指针投射到另一个智能指针,例如将std::shared_ptr<Z>投射到std::shared_ptr<X>?这有用吗?这是允许的吗?

请注意,我明确地引用了非侵入式指针(作为C ++ 0x中的新std::shared_ptrstd::weak_ptr)。当使用侵入式指针(如Boost)时,它可能有效,因为实例本身负责保留计数器。

1 个答案:

答案 0 :(得分:6)

是的,标准§20.9.11.2.10[util.smartptr.shared.cast]支持这一点。

您需要的工具是:

  • std::static_pointer_cast<>()
  • std::dynamic_pointer_cast<>()

它们与C ++ 03计数器部分static_cast<>()dynamic_cast<>()具有相同的语义。一个区别是它们只适用于std::shared_ptr s。只是为了详细,他们按照您的期望行事并正确地分享原始shared_ptr之间的引用计数。

struct X { virtual ~X(){} };
struct Y : public X {};
struct Z : public X {};

int main()
{
   {
      //C++03
      X* x = new Z;
      Z* z = dynamic_cast<Z*>(x);
      assert(z);
      x = new Y;
      z = dynamic_cast<Z*>(x);
      assert(!z);
      z = static_cast<Z*>(x);
      assert(z); //EVIL!!!
   }

   {
      //C++0x
      std::shared_ptr<X> x{new Z};
      std::shared_ptr<Z> z{std::dynamic_pointer_cast<Z>(x)};
      assert(z);
      x = std::make_shared<Y>();
      z = std::dynamic_pointer_cast<Z>(x);
      assert(!z);
      z = std::static_pointer_cast<Z>(x);
      assert(z); //EVIL!!!

      // reference counts work as expected.
      std::shared_ptr<Y> y{std::static_pointer_cast<Y>(x)};
      assert(y);

      std::weak_ptr<Y> w{y};
      assert(w.expired());

      y.reset();
      assert(w.expired());

      x.reset();
      assert(!w.expired());      
   }
   {
      //s'more nice shared_ptr features
      auto z = std::make_shared<X>();
      std::shared_ptr<X> x{z};
      assert( z == x );
      x = z; //assignment also works.
   }
}