VTK source code reading--the smart pointer vtkSmartPointer class in VTK

class vtkSmartPointer

        vtkSmartPointer is a class template that provides automatic coercion for objects held by the vtkSmartPointerBase superclass.

#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

class vtkSmartPointerBase

        The vtkSmartPointerBase class holds a pointer to vtkObjectBase or a subclass instance, and executes Register/UnRegister. This is useful for storing VTK objects in STL containers. The vtkSmartPointerBase class is usually not used directly, and the vtkSmartPointer class template is often used to automatically perform the correct cast operation.

         Declaration of vtkSmartPointerBase class:

#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

         The implementation of the vtkSmartPointerBase class focuses on the overloading of the assignment operator and the implementation of the Swap function; its core is the call to the Register and UnRegister of the internal object Object;

        In the Swap function, the construction and destruction of local variables and the interactive processing of the target pointer are cleverly used; similar to std::vector().swap(deleted_vec), the space inside deleted_vec is released;

#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());
}

Guess you like

Origin blog.csdn.net/liushao1031177/article/details/124609049