VTK源码阅读--VTK里的智能指针vtkSmartPointer类

vtkSmartPointer类

        vtkSmartPointer是一个类模板,为vtkSmartPointerBase超类持有的对象提供自动强制转换。

#ifndef vtkSmartPointer_h
#define vtkSmartPointer_h

#include "vtkSmartPointerBase.h"
#include "vtkMeta.h"    // for IsComplete
#include "vtkNew.h"     // for vtkNew.h
#include <type_traits>  // for is_base_of
#include <utility>      // for std::move

template <class T>
class vtkSmartPointer : public vtkSmartPointerBase
{
  // 这些静态断言仅在使用调用CheckTypes的函数时触发。
  // 因此,只要在使用调用函数时定义了T,这个智能指针类仍然可以用作前向声明T的成员变量。
  template <typename U = T>
  static void CheckTypes() noexcept
  {
    // 判断T类型是否已经被定义,是否缺少了include<T>
    static_assert(vtk::detail::IsComplete<T>::value,
      "vtkSmartPointer<T>'s T type has not been defined. Missing "
      "include?");
    // 提示不能加载一个无定义的对象类型,事情缺少include<T>
    static_assert(vtk::detail::IsComplete<U>::value,
      "Cannot store an object with undefined type in "
      "vtkSmartPointer. Missing include?");
    // 提示不完整的参数类型
    static_assert(std::is_base_of<T, U>::value,
      "Argument type is not compatible with vtkSmartPointer<T>'s "
      "T type.");
    // vtkSmartPointer只能被用于vtkObjectBase的子类
    static_assert(std::is_base_of<vtkObjectBase, T>::value,
      "vtkSmartPointer can only be used with subclasses of "
      "vtkObjectBase.");
  }

public:
  // 初始智能指针内部指针为空;
  vtkSmartPointer() noexcept : vtkSmartPointerBase() {}

  // 根据传入的智能指针的引用,初始智能指针指向相同的Ojbect;
  // 需要两个重载,因为拷贝构造函数必须是非模板的;
  vtkSmartPointer(const vtkSmartPointer& r)
    : vtkSmartPointerBase(r) { }
  template <class U>
  vtkSmartPointer(const vtkSmartPointer<U>& r)
    : vtkSmartPointerBase(r)
  {
    vtkSmartPointer::CheckTypes<U>();
  }

  // 移动语义,将r内的对象转移到this内;
  // 需要两个重载,因为移动构造函数必须是非模板的;
  vtkSmartPointer(vtkSmartPointer&& r) noexcept : vtkSmartPointerBase(std::move(r)) {}

  template <class U>
  vtkSmartPointer(vtkSmartPointer<U>&& r) noexcept : vtkSmartPointerBase(std::move(r))
  {
    vtkSmartPointer::CheckTypes<U>();
  }

  // 根据传入对象的指针,构造智能指针;
  vtkSmartPointer(T* r)
    : vtkSmartPointerBase(r)
  {
    vtkSmartPointer::CheckTypes();
  }
  // 从vtkNew中的对象Object,复制出一个新的引用,增加了Object的引用计数;
  template <typename U>
  vtkSmartPointer(const vtkNew<U>& r)
    : vtkSmartPointerBase(r.Object)
  {
    vtkSmartPointer::CheckTypes<U>();
  }

  // 右值构造函数
  // 移动vtkNew中的对象指针,并以此指针构建vtkSmartPointer对象;
  // 构造后,将原vtkNew中的对象指针设置为nullptr;
  template <typename U>
  vtkSmartPointer(vtkNew<U>&& r) noexcept
    : vtkSmartPointerBase(r.Object, vtkSmartPointerBase::NoReference{})
  {
    vtkSmartPointer::CheckTypes<U>();
    r.Object = nullptr;
  }

  // 赋值运算符重载
  // 修改对象指针为r内的Object,将原来的Object指向的引用个数减少;
  // 因为编译器不会将模板函数识别为赋值运算符,所以分成两个重载函数;
  vtkSmartPointer& operator=(const vtkSmartPointer& r)
  {
    this->vtkSmartPointerBase::operator=(r.GetPointer());
    return *this;
  }
  template <class U>
  vtkSmartPointer& operator=(const vtkSmartPointer<U>& r)
  {
    vtkSmartPointer::CheckTypes<U>();

    this->vtkSmartPointerBase::operator=(r.GetPointer());
    return *this;
  }

  // 从vtkNew赋值运算;
  template <typename U>
  vtkSmartPointer& operator=(const vtkNew<U>& r)
  {
    vtkSmartPointer::CheckTypes<U>();

    this->vtkSmartPointerBase::operator=(r.Object);
    return *this;
  }

  // 由对象指针赋值,将Object指向新的指针;
  template <typename U>
  vtkSmartPointer& operator=(U* r)
  {
    vtkSmartPointer::CheckTypes<U>();

    this->vtkSmartPointerBase::operator=(r);
    return *this;
  }

  // 获取智能指针内部的原始指针;
  T* GetPointer() const noexcept { return static_cast<T*>(this->Object); }
  T* Get() const noexcept { return static_cast<T*>(this->Object); }
  // 重载()运算符,获取智能指针内部的原始指针;
  operator T*() const noexcept { return static_cast<T*>(this->Object); }

  // 重载解引用运算符,返回内部对象的一个引用;
  T& operator*() const noexcept { return *static_cast<T*>(this->Object); }

  // 使用运算符->提供正常的指针目标成员访问;
  T* operator->() const noexcept { return static_cast<T*>(this->Object); }

  // 将传入VTK对象的一个引用的所有权转移到此智能指针。
  // 这不会增加对象的引用计数,但稍后会减少它。
  // 调用方实际上是将一个引用的所有权传递给智能指针。
  // 使用的方式如下:
  //    vtkSmartPointer<vtkFoo> foo;
  //    foo.TakeReference(bar->NewFoo());
  // 输入参数不可以是其他智能指针;
  void TakeReference(T* t) { *this = vtkSmartPointer<T>(t, NoReference()); }

  // 创建一个T类型的智能指针;
  static vtkSmartPointer<T> New() { return vtkSmartPointer<T>(T::New(), NoReference()); }

  // 根据传入的对象指针,创建一个新的实例;
  static vtkSmartPointer<T> NewInstance(T* t)
  {
    return vtkSmartPointer<T>(t->NewInstance(), NoReference());
  }

  static vtkSmartPointer<T> Take(T* t) { return vtkSmartPointer<T>(t, NoReference()); }

  // Work-around for HP and IBM overload resolution bug.  Since
  // NullPointerOnly is a private type the only pointer value that can
  // be passed by user code is a null pointer.  This operator will be
  // chosen by the compiler when comparing against null explicitly and
  // avoid the bogus ambiguous overload error.
#if defined(__HP_aCC) || defined(__IBMCPP__)
#define VTK_SMART_POINTER_DEFINE_OPERATOR_WORKAROUND(op)                                           \
  bool operator op(NullPointerOnly*) const { return ::operator op(*this, 0); }

private:
  class NullPointerOnly
  {
  };

public:
  VTK_SMART_POINTER_DEFINE_OPERATOR_WORKAROUND(==)
  VTK_SMART_POINTER_DEFINE_OPERATOR_WORKAROUND(!=)
  VTK_SMART_POINTER_DEFINE_OPERATOR_WORKAROUND(<)
  VTK_SMART_POINTER_DEFINE_OPERATOR_WORKAROUND(<=)
  VTK_SMART_POINTER_DEFINE_OPERATOR_WORKAROUND(>)
  VTK_SMART_POINTER_DEFINE_OPERATOR_WORKAROUND(>=)
#undef VTK_SMART_POINTER_DEFINE_OPERATOR_WORKAROUND
#endif
protected:
  vtkSmartPointer(T* r, const NoReference& n)
    : vtkSmartPointerBase(r, n)
  {
  }

private:
  // 这些是故意不实现的,以防止调用方尝试从其他智能指针获取引用。
  void TakeReference(const vtkSmartPointerBase&) = delete;
  static void Take(const vtkSmartPointerBase&) = delete;
};

#define VTK_SMART_POINTER_DEFINE_OPERATOR(op)                                                      \
  template <class T, class U>                                                                      \
  inline bool operator op(const vtkSmartPointer<T>& l, const vtkSmartPointer<U>& r)                \
  {                                                                                                \
    return (l.GetPointer() op r.GetPointer());                                                     \
  }                                                                                                \
  template <class T, class U>                                                                      \
  inline bool operator op(T* l, const vtkSmartPointer<U>& r)                                       \
  {                                                                                                \
    return (l op r.GetPointer());                                                                  \
  }                                                                                                \
  template <class T, class U>                                                                      \
  inline bool operator op(const vtkSmartPointer<T>& l, U* r)                                       \
  {                                                                                                \
    return (l.GetPointer() op r);                                                                  \
  }                                                                                                \
  template <class T, class U>                                                                      \
  inline bool operator op(const vtkNew<T>& l, const vtkSmartPointer<U>& r)                         \
  {                                                                                                \
    return (l.GetPointer() op r.GetPointer());                                                     \
  }                                                                                                \
  template <class T, class U>                                                                      \
  inline bool operator op(const vtkSmartPointer<T>& l, const vtkNew<U>& r)                         \
  {                                                                                                \
    return (l.GetPointer() op r.GetPointer);                                                       \
  }

// 智能指针比较运算符重载
VTK_SMART_POINTER_DEFINE_OPERATOR(==)
VTK_SMART_POINTER_DEFINE_OPERATOR(!=)
VTK_SMART_POINTER_DEFINE_OPERATOR(<)
VTK_SMART_POINTER_DEFINE_OPERATOR(<=)
VTK_SMART_POINTER_DEFINE_OPERATOR(>)
VTK_SMART_POINTER_DEFINE_OPERATOR(>=)
#undef VTK_SMART_POINTER_DEFINE_OPERATOR

namespace vtk
{
    // 根据传入的指针构建,obj的引用计数增加了;
    template <typename T>
    vtkSmartPointer<T> MakeSmartPointer(T* obj)
    {
      return vtkSmartPointer<T>{ obj };
    }

    // 根据传入的指针构建,obj的引用计数不会增加;
    template <typename T>
    vtkSmartPointer<T> TakeSmartPointer(T* obj)
    {
      return vtkSmartPointer<T>::Take(obj);
    }
}

// Streaming operator可以像普通指针一样打印智能指针。
template <class T>
inline ostream& operator<<(ostream& os, const vtkSmartPointer<T>& p)
{
  return os << static_cast<const vtkSmartPointerBase&>(p);
}

#endif

vtkSmartPointerBase类

        vtkSmartPointerBase类内持有了一个指向vtkObjectBase或子类实例的指针,并执行Register/UnRegister。这对于在STL容器中存储VTK对象很有用。通常不会直接使用 vtkSmartPointerBase类,往往会使用vtkSmartPointer类模板自动执行正确的强制转换操作。

         vtkSmartPointerBase类的声明:

#ifndef vtkSmartPointerBase_h
#define vtkSmartPointerBase_h

#include "vtkCommonCoreModule.h"
#include "vtkObjectBase.h"

class VTKCOMMONCORE_EXPORT vtkSmartPointerBase
{
public:
  // 初始化智能指针为nullptr
  vtkSmartPointerBase();
  // 使用一个给定的指针初始化智能指针
  vtkSmartPointerBase(vtkObjectBase* r);
  // 使用一个智能指针对象初始化智能指针,在同一个对象上增加一个新的引用(引用计数加一);
  vtkSmartPointerBase(const vtkSmartPointerBase& r);
  // 销毁智能指针,并将对象的引用删除(引用计数减一);
  ~vtkSmartPointerBase();
  // 将对象指定给引用。这将删除对旧对象的任何引用。
  vtkSmartPointerBase& operator=(vtkObjectBase* r);
  vtkSmartPointerBase& operator=(const vtkSmartPointerBase& r);
  // 获取对象内包含的指针
  vtkObjectBase* GetPointer() const
  {
    // 内联实现,因此智能指针可以将比较运算完全内联。
    return this->Object;
  }
  // 将智能指针持有的引用报告给collector。
  void Report(vtkGarbageCollector* collector, const char* desc);

protected:
  // 初始化指向给定对象的智能指针,但不要增加引用计数。
  // 析构函数仍然会减少计数。
  // 这实际上使其成为auto_ptr。
  class NoReference {};
  vtkSmartPointerBase(vtkObjectBase* r, const NoReference&);
  // 指向实际的对象指针.
  vtkObjectBase* Object;
private:
  // 内部公用方法.
  void Swap(vtkSmartPointerBase& r);
  void Register();
};

#define VTK_SMART_POINTER_BASE_DEFINE_OPERATOR(op) \
  inline bool \
  operator op (const vtkSmartPointerBase& l, const vtkSmartPointerBase& r) \
  { \
    return (static_cast<void*>(l.GetPointer()) op \
            static_cast<void*>(r.GetPointer())); \
  } \
  inline bool \
  operator op (vtkObjectBase* l, const vtkSmartPointerBase& r) \
  { \
    return (static_cast<void*>(l) op static_cast<void*>(r.GetPointer())); \
  } \
  inline bool \
  operator op (const vtkSmartPointerBase& l, vtkObjectBase* r) \
  { \
    return (static_cast<void*>(l.GetPointer()) op static_cast<void*>(r)); \
  }

// 比较操作运算符重载
VTK_SMART_POINTER_BASE_DEFINE_OPERATOR(==)
VTK_SMART_POINTER_BASE_DEFINE_OPERATOR(!=)
VTK_SMART_POINTER_BASE_DEFINE_OPERATOR(<)
VTK_SMART_POINTER_BASE_DEFINE_OPERATOR(<=)
VTK_SMART_POINTER_BASE_DEFINE_OPERATOR(>)
VTK_SMART_POINTER_BASE_DEFINE_OPERATOR(>=)

#undef VTK_SMART_POINTER_BASE_DEFINE_OPERATOR

VTKCOMMONCORE_EXPORT ostream& operator << (ostream& os,
                                        const vtkSmartPointerBase& p);

#endif

         vtkSmartPointerBase类的实现重点在于赋值运算符的重载中,以及Swap函数的实现;其核心就是对内部对象Object的Register和UnRegister的调用;

        在Swap函数中,巧妙的使用了局部变量的构建和析构与目标指针的交互处理;类似std::vecter().swap(deleted_vec)的方式释放deleted_vec内部的空间;

#include "vtkSmartPointerBase.h"
#include "vtkGarbageCollector.h"

vtkSmartPointerBase::vtkSmartPointerBase():
  Object(nullptr)
{
  // 对object增加一个引用
  this->Register();
}

vtkSmartPointerBase::vtkSmartPointerBase(vtkObjectBase* r):
  Object(r)
{
  //  对object增加一个引用
  this->Register();
}

vtkSmartPointerBase::vtkSmartPointerBase(vtkObjectBase* r, const NoReference&):
  Object(r)
{
  // 由于参数类型时NoReference,所以不会增加object的引用
}

vtkSmartPointerBase::vtkSmartPointerBase(const vtkSmartPointerBase& r):
  Object(r.Object)
{
  // 对object增加一个引用
  this->Register();
}

vtkSmartPointerBase::~vtkSmartPointerBase()
{
  // 在调用UnRegister释放Object所指向的引用之前,需要将Object设置为nullptr,
  // 所以,用了一个本地变量object记录了Object的指针地址;
  // 这是因为垃圾收集引用图遍历可能会返回这个智能指针,我们不想包含这个引用。
  vtkObjectBase* object = this->Object;
  if(object) {
    this->Object = nullptr;
    object->UnRegister(nullptr);
  }
}

vtkSmartPointerBase&
vtkSmartPointerBase::operator=(vtkObjectBase* r)
{
  // 这是一个异常安全的分配习惯用法,它还为所有相关对象提供了正确的register/unregister调用顺序。
  // 使用r指针构建一个新的vtkSmartPointerBase对象;
  // 新对象内的Object指针与*this内的Object指针交互;
  // 新对象在函数结束后,自动析构,释放Ojbect;
  vtkSmartPointerBase(r).Swap(*this);
  return *this;
}

vtkSmartPointerBase&
vtkSmartPointerBase::operator=(const vtkSmartPointerBase& r)
{
  vtkSmartPointerBase(r).Swap(*this);
  return *this;
}

void vtkSmartPointerBase::Report(vtkGarbageCollector* collector,
                                 const char* desc)
{
  vtkGarbageCollectorReport(collector, this->Object, desc);
}

void vtkSmartPointerBase::Swap(vtkSmartPointerBase& r)
{
  // 交互两个对象内部的Object指针.
  // Swap方法被用于赋值运算符重载实现中;
  vtkObjectBase* temp = r.Object;
  r.Object = this->Object;
  this->Object = temp;
}

void vtkSmartPointerBase::Register()
{
  // 如果Object不为空时,增加Object的引用计数;
  if(this->Object) {
    this->Object->Register(nullptr);
  }
}

ostream& operator << (ostream& os, const vtkSmartPointerBase& p)
{
  // 只是打印p内的Object指针地址到stream中;
  return os << static_cast<void*>(p.GetPointer());
}

猜你喜欢

转载自blog.csdn.net/liushao1031177/article/details/124609049
今日推荐