vtkSmartPointer是一个类模板,为vtkSmartPointerBase超类持有的对象提供自动强制转换。
#ifndef vtkSmartPointer_h
#define vtkSmartPointer_h
#include "vtkSmartPointerBase.h"
#include "vtkMeta.h" // for IsComplete
#include "vtkNew.h" // for vtkNew.h
#include // for is_base_of
#include // for std::move
template
class vtkSmartPointer : public vtkSmartPointerBase
{
// 这些静态断言仅在使用调用CheckTypes的函数时触发。
// 因此,只要在使用调用函数时定义了T,这个智能指针类仍然可以用作前向声明T的成员变量。
template
static void CheckTypes() noexcept
{
// 判断T类型是否已经被定义,是否缺少了include
static_assert(vtk::detail::IsComplete::value,
"vtkSmartPointer's T type has not been defined. Missing "
"include?");
// 提示不能加载一个无定义的对象类型,事情缺少include
static_assert(vtk::detail::IsComplete::value,
"Cannot store an object with undefined type in "
"vtkSmartPointer. Missing include?");
// 提示不完整的参数类型
static_assert(std::is_base_of::value,
"Argument type is not compatible with vtkSmartPointer's "
"T type.");
// vtkSmartPointer只能被用于vtkObjectBase的子类
static_assert(std::is_base_of::value,
"vtkSmartPointer can only be used with subclasses of "
"vtkObjectBase.");
}
public:
// 初始智能指针内部指针为空;
vtkSmartPointer() noexcept : vtkSmartPointerBase() {}
// 根据传入的智能指针的引用,初始智能指针指向相同的Ojbect;
// 需要两个重载,因为拷贝构造函数必须是非模板的;
vtkSmartPointer(const vtkSmartPointer& r)
: vtkSmartPointerBase(r) { }
template
vtkSmartPointer(const vtkSmartPointer& r)
: vtkSmartPointerBase(r)
{
vtkSmartPointer::CheckTypes();
}
// 移动语义,将r内的对象转移到this内;
// 需要两个重载,因为移动构造函数必须是非模板的;
vtkSmartPointer(vtkSmartPointer&& r) noexcept : vtkSmartPointerBase(std::move(r)) {}
template
vtkSmartPointer(vtkSmartPointer&& r) noexcept : vtkSmartPointerBase(std::move(r))
{
vtkSmartPointer::CheckTypes();
}
// 根据传入对象的指针,构造智能指针;
vtkSmartPointer(T* r)
: vtkSmartPointerBase(r)
{
vtkSmartPointer::CheckTypes();
}
// 从vtkNew中的对象Object,复制出一个新的引用,增加了Object的引用计数;
template
vtkSmartPointer(const vtkNew& r)
: vtkSmartPointerBase(r.Object)
{
vtkSmartPointer::CheckTypes();
}
// 右值构造函数
// 移动vtkNew中的对象指针,并以此指针构建vtkSmartPointer对象;
// 构造后,将原vtkNew中的对象指针设置为nullptr;
template
vtkSmartPointer(vtkNew&& r) noexcept
: vtkSmartPointerBase(r.Object, vtkSmartPointerBase::NoReference{})
{
vtkSmartPointer::CheckTypes();
r.Object = nullptr;
}
// 赋值运算符重载
// 修改对象指针为r内的Object,将原来的Object指向的引用个数减少;
// 因为编译器不会将模板函数识别为赋值运算符,所以分成两个重载函数;
vtkSmartPointer& operator=(const vtkSmartPointer& r)
{
this->vtkSmartPointerBase::operator=(r.GetPointer());
return *this;
}
template
vtkSmartPointer& operator=(const vtkSmartPointer& r)
{
vtkSmartPointer::CheckTypes();
this->vtkSmartPointerBase::operator=(r.GetPointer());
return *this;
}
// 从vtkNew赋值运算;
template
vtkSmartPointer& operator=(const vtkNew& r)
{
vtkSmartPointer::CheckTypes();
this->vtkSmartPointerBase::operator=(r.Object);
return *this;
}
// 由对象指针赋值,将Object指向新的指针;
template
vtkSmartPointer& operator=(U* r)
{
vtkSmartPointer::CheckTypes();
this->vtkSmartPointerBase::operator=(r);
return *this;
}
// 获取智能指针内部的原始指针;
T* GetPointer() const noexcept { return static_cast(this->Object); }
T* Get() const noexcept { return static_cast(this->Object); }
// 重载()运算符,获取智能指针内部的原始指针;
operator T*() const noexcept { return static_cast(this->Object); }
// 重载解引用运算符,返回内部对象的一个引用;
T& operator*() const noexcept { return *static_cast(this->Object); }
// 使用运算符->提供正常的指针目标成员访问;
T* operator->() const noexcept { return static_cast(this->Object); }
// 将传入VTK对象的一个引用的所有权转移到此智能指针。
// 这不会增加对象的引用计数,但稍后会减少它。
// 调用方实际上是将一个引用的所有权传递给智能指针。
// 使用的方式如下:
// vtkSmartPointer foo;
// foo.TakeReference(bar->NewFoo());
// 输入参数不可以是其他智能指针;
void TakeReference(T* t) { *this = vtkSmartPointer(t, NoReference()); }
// 创建一个T类型的智能指针;
static vtkSmartPointer New() { return vtkSmartPointer(T::New(), NoReference()); }
// 根据传入的对象指针,创建一个新的实例;
static vtkSmartPointer NewInstance(T* t)
{
return vtkSmartPointer(t->NewInstance(), NoReference());
}
static vtkSmartPointer Take(T* t) { return vtkSmartPointer(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 \
inline bool operator op(const vtkSmartPointer& l, const vtkSmartPointer& r) \
{ \
return (l.GetPointer() op r.GetPointer()); \
} \
template \
inline bool operator op(T* l, const vtkSmartPointer& r) \
{ \
return (l op r.GetPointer()); \
} \
template \
inline bool operator op(const vtkSmartPointer& l, U* r) \
{ \
return (l.GetPointer() op r); \
} \
template \
inline bool operator op(const vtkNew& l, const vtkSmartPointer& r) \
{ \
return (l.GetPointer() op r.GetPointer()); \
} \
template \
inline bool operator op(const vtkSmartPointer& l, const vtkNew& 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
vtkSmartPointer MakeSmartPointer(T* obj)
{
return vtkSmartPointer{ obj };
}
// 根据传入的指针构建,obj的引用计数不会增加;
template
vtkSmartPointer TakeSmartPointer(T* obj)
{
return vtkSmartPointer::Take(obj);
}
}
// Streaming operator可以像普通指针一样打印智能指针。
template
inline ostream& operator<<(ostream& os, const vtkSmartPointer& p)
{
return os << static_cast(p);
}
#endif
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(l.GetPointer()) op \
static_cast(r.GetPointer())); \
} \
inline bool \
operator op (vtkObjectBase* l, const vtkSmartPointerBase& r) \
{ \
return (static_cast(l) op static_cast(r.GetPointer())); \
} \
inline bool \
operator op (const vtkSmartPointerBase& l, vtkObjectBase* r) \
{ \
return (static_cast(l.GetPointer()) op static_cast(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(p.GetPointer());
}