vtkWeakPointerBase クラス
vtkWeakPointerBase クラスは、 vtkObjectBase または vtkObjectBase 派生クラスへのポインターを保持しますが、vtkObjectBaseの参照カウントには決して影響しません。ただし、参照されたvtkObjectBaseが破棄されると、ポインタは nullptr に初期化されるため、ダングリング参照が回避されます。
vtkWeakPointerBase クラス オブジェクトを使用すると、オブジェクトが指す vtkObjectBase 内の WeakPointers が変更されます。
vtkWeakPointerBase クラス宣言
vtkWeakPointerBase クラスのヘッダー ファイル宣言は次のとおりです。
class VTKCOMMONCORE_EXPORT vtkWeakPointerBase
{
public:
// 构造函数,将成员变量Object设置为空指针
vtkWeakPointerBase() noexcept : Object(nullptr) {}
// 构造函数,将成员变量Object设置为传入的指针
vtkWeakPointerBase(vtkObjectBase* r);
// 拷贝构造函数,将右值的data传入
vtkWeakPointerBase(const vtkWeakPointerBase& r);
// Move语义,将右值的Object指针转移到新vtkWeakPointerBase对象
vtkWeakPointerBase(vtkWeakPointerBase&& r) noexcept;
// 析构函数
~vtkWeakPointerBase();
//@{
// 重载赋值运算符,使用新的引用覆盖旧的引用
vtkWeakPointerBase& operator=(vtkObjectBase* r);
vtkWeakPointerBase& operator=(const vtkWeakPointerBase& r);
vtkWeakPointerBase& operator=(vtkWeakPointerBase&& r) noexcept;
//@}
// 获取对象包含的原指针
vtkObjectBase* GetPointer() const
{
// 以内联函数方式实现,所以智能指针比较可以完全内联;
return this->Object;
}
private:
friend class vtkObjectBaseToWeakPointerBaseFriendship;
protected:
// Initialize weak pointer to given object.
class NoReference
{
};
vtkWeakPointerBase(vtkObjectBase* r, const NoReference&);
// 指向原对象的指针
vtkObjectBase* Object;
};
ここで、vtkObjectBaseToWeakPointerBaseFriendship はそのメンバー変数 Object を直接操作し、vtkObjectBase クラスで使用されるため、vtkObjectBaseToWeakPointerBaseFriendship は vtkWeakPointerBase クラスのフレンド クラスとして設定されます。
vtkObjectBase.cxx ファイルでは、vtkObjectBaseToWeakPointerBaseFriendship クラスが定義されています。
class vtkObjectBaseToWeakPointerBaseFriendship
{
public:
static void ClearPointer(vtkWeakPointerBase* p) { p->Object = nullptr; }
};
6 つの比較演算子は、 マクロVTK_WEAK_POINTER_BASE_DEFINE_OPERATORを使用してオーバーロードされます。
#define VTK_WEAK_POINTER_BASE_DEFINE_OPERATOR(op) \
inline bool operator op(const vtkWeakPointerBase& l, const vtkWeakPointerBase& r) \
{ \
return (static_cast<void*>(l.GetPointer()) op static_cast<void*>(r.GetPointer())); \
} \
inline bool operator op(vtkObjectBase* l, const vtkWeakPointerBase& r) \
{ \
return (static_cast<void*>(l) op static_cast<void*>(r.GetPointer())); \
} \
inline bool operator op(const vtkWeakPointerBase& l, vtkObjectBase* r) \
{ \
return (static_cast<void*>(l.GetPointer()) op static_cast<void*>(r)); \
}
/**
* Compare smart pointer values.
*/
VTK_WEAK_POINTER_BASE_DEFINE_OPERATOR(==)
VTK_WEAK_POINTER_BASE_DEFINE_OPERATOR(!=)
VTK_WEAK_POINTER_BASE_DEFINE_OPERATOR(<)
VTK_WEAK_POINTER_BASE_DEFINE_OPERATOR(<=)
VTK_WEAK_POINTER_BASE_DEFINE_OPERATOR(>)
VTK_WEAK_POINTER_BASE_DEFINE_OPERATOR(>=)
#undef VTK_WEAK_POINTER_BASE_DEFINE_OPERATOR
vtkWeakPointerBase クラスの実装
コンストラクターはメンバー変数 Object を r にポイントし、
vtkWeakPointerBaseToObjectBaseFriendship の AddWeakPointer メソッドを使用して、このレコードを r の WeakPointers に追加します。
vtkWeakPointerBase::vtkWeakPointerBase(vtkObjectBase* r)
: Object(r)
{
vtkWeakPointerBaseToObjectBaseFriendship::AddWeakPointer(r, this);
}
vtkWeakPointerBase::vtkWeakPointerBase(const vtkWeakPointerBase& r)
: Object(r.Object)
{
vtkWeakPointerBaseToObjectBaseFriendship::AddWeakPointer(r.Object, this);
}
移動セマンティクスを実装するには、右辺値オブジェクトを null に設定し、vtkWeakPointerBaseToObjectBaseFriendship の ReplaceWeakPointer メソッドを呼び出して、Object が指す vtkObjectBase の WeakPointers の r レコードをこの情報で置き換えます。
vtkWeakPointerBase::vtkWeakPointerBase(vtkWeakPointerBase&& r) noexcept : Object(r.Object)
{
r.Object = nullptr;
vtkWeakPointerBaseToObjectBaseFriendship::ReplaceWeakPointer(this->Object, &r, this);
}
デストラクターの実装は、最初に vtkWeakPointerBaseToObjectBaseFriendship の RemoveWeakPointer メソッドを呼び出して、これに対応するレコードをオブジェクトの WeakPointers から削除し、オブジェクトを空に設定します。
vtkWeakPointerBase::~vtkWeakPointerBase()
{
vtkWeakPointerBaseToObjectBaseFriendship::RemoveWeakPointer(this->Object, this);
this->Object = nullptr;
}
オーバーロードされた代入演算子の実装:
vtkWeakPointerBase& vtkWeakPointerBase::operator=(vtkObjectBase* r)
{
// 当前Object指向的vtkObjectBase跟r不是同一个对象;
if (this->Object != r) {
// 1.将Object原本指向的vtkObjectBase内的WeakPointers中删除this信息;
vtkWeakPointerBaseToObjectBaseFriendship::RemoveWeakPointer(this->Object, this);
// 2.将Object指向新的vtkObjectBase;
this->Object = r;
// 3.在新的vtkObjectBase中的WeakPointers追加this信息;
vtkWeakPointerBaseToObjectBaseFriendship::AddWeakPointer(this->Object, this);
}
// 返回当前对象的引用;
return *this;
}
vtkWeakPointerBase& vtkWeakPointerBase::operator=(const vtkWeakPointerBase& r)
{
// 当前对象地址与r对象的地址不同;
if (this != &r) {
// 当前对象内的Object指针和r内的Object指针不是相同的地址时;
if (this->Object != r.Object) {
// 1.将Object原本指向的vtkObjectBase内的WeakPointers中删除this信息;
vtkWeakPointerBaseToObjectBaseFriendship::RemoveWeakPointer(this->Object, this);
// 2.将Object指向新的vtkObjectBase;
this->Object = r.Object;
// 3.在新的vtkObjectBase中的WeakPointers追加this信息;
vtkWeakPointerBaseToObjectBaseFriendship::AddWeakPointer(this->Object, this);
}
}
// 返回当前对象的引用;
return *this;
}
vtkWeakPointerBase& vtkWeakPointerBase::operator=(vtkWeakPointerBase&& r) noexcept
{
// 当前对象地址与右值r对象的地址不同;
if (this != &r) {
// 当前对象内的Object指针和r内的Object指针不是相同的地址时;
if (this->Object != r.Object) {
// 1.将Object原本指向的vtkObjectBase内的WeakPointers中删除this信息;
vtkWeakPointerBaseToObjectBaseFriendship::RemoveWeakPointer(this->Object, this);
// WTB std::exchange
// 2.将Object指向新的vtkObjectBase;
this->Object = r.Object;
// 3.将r对象内的Object设置为空,因为已经将它转移到了当前对象的Object中;
r.Object = nullptr;
// 4.在新的vtkObjectBase中的WeakPointers追加this信息;
vtkWeakPointerBaseToObjectBaseFriendship::ReplaceWeakPointer(this->Object, &r, this);
}
}
// 返回当前对象的引用;
return *this;
}
vtkWeakPointerBaseToObjectBaseFriendship类
vtkWeakPointerBaseToObjectBaseFriendship クラスは、vtkWeakPointerBase クラスの基礎となる実装であり、宣言と定義は「vtkWeakPointerBase.cxx」ファイルにあります。
class vtkWeakPointerBaseToObjectBaseFriendship
{
public:
static void AddWeakPointer(vtkObjectBase* r, vtkWeakPointerBase* p);
static void RemoveWeakPointer(vtkObjectBase* r, vtkWeakPointerBase* p) noexcept;
static void ReplaceWeakPointer(
vtkObjectBase* r, vtkWeakPointerBase* bad, vtkWeakPointerBase* good) noexcept;
};
AddWeakPointer の実装:
その機能は、新しい要素 p を r の WeakPointers リストに追加することです。
void vtkWeakPointerBaseToObjectBaseFriendship::AddWeakPointer(
vtkObjectBase* r, vtkWeakPointerBase* p)
{
if (r) {
vtkWeakPointerBase** l = r->WeakPointers;
// 如果r的列表为空,即l==nullptr,需要创建一个新的vtkWeakPointerBase指针数组;
if (l == nullptr) {
// 创建一个含有两个元素的vtkWeakPointerBase*数组;
l = new vtkWeakPointerBase*[2];
l[0] = p;
// 将末尾元素设置为nullptr,作为边界值;
l[1] = nullptr;
r->WeakPointers = l;
}
else {
// 根据l的末尾元素为nullptr,则可以遍历到l的末尾,获取l的长度n;
size_t n = 0;
while (l[n] != nullptr) {
n++;
}
//
// 如果n+1是2的幂,则将列表大小增加一倍;
if ((n & (n + 1)) == 0) {
// 用局部变量t暂存l的旧指针,之后会用来释放旧指针指向的内存空间;
vtkWeakPointerBase** t = l;
// 重新分配给l一个个数为(n + 1) * 2的vtkWeakPointerBase指针数组;
l = new vtkWeakPointerBase*[(n + 1) * 2];
// 将l原来空间内元素拷贝到新的内存空间中,这里为什么不使用memcpy???
for (size_t i = 0; i < n; i++) {
l[i] = t[i];
}
// 释放原来内存空间;
delete[] t;
// 更新r的WeakPointers指向新的列表;
r->WeakPointers = l;
}
// 将p放在末尾位置;
l[n++] = p;
// 将l列表末尾设置为nullptr;
l[n] = nullptr;
}
}
}
RemoveWeakPointer メソッドの実装:
その機能は、r の WeakPointers から p ポインタを削除することです。
void vtkWeakPointerBaseToObjectBaseFriendship::RemoveWeakPointer(
vtkObjectBase* r, vtkWeakPointerBase* p) noexcept
{
// 如果r不为空时;
if (r) {
vtkWeakPointerBase** l = r->WeakPointers;
// 如果r内的WeakPointers不为空时;
// 删除p的方式是,定位到p的前一个位置,然后将p之后的元素向前平移一个位置;
if (l != nullptr) {
size_t i = 0;
// 定位p的下标i;
while (l[i] != nullptr && l[i] != p) {
i++;
}
// 从i开始,将i+1元素向前平移;
while (l[i] != nullptr) {
l[i] = l[i + 1];
i++;
}
// 如果l第一个元素为nullptr,表示l列表内有0个元素;
// 则删除l;将r内的WeakPointers置为空;
if (l[0] == nullptr) {
delete[] l;
r->WeakPointers = nullptr;
}
}
}
}
ReplaceWeakPointer の実装は次のとおりです。
その機能は次のとおりです。 r の WeakPointers リスト内の bad を Good に置き換えます。
void vtkWeakPointerBaseToObjectBaseFriendship::ReplaceWeakPointer(
vtkObjectBase* r, vtkWeakPointerBase* bad, vtkWeakPointerBase* good) noexcept
{
// 当r不为空时;
if (r) {
vtkWeakPointerBase** l = r->WeakPointers;
// 当r的WeakPointers列表不为空时;
if (l != nullptr) {
// 遍历l中元素,找到bad,然后替换为good;
for (; *l != nullptr; ++l) {
if (*l == bad) {
*l = good;
break;
}
}
}
}
}