測試智能指針是否為 NULL
在Qt的項目中,osg里有智能指針
osg::ref_ptr<int> a;
然后可能和C++標准庫不同 ,在判斷智能指針是否為空的時候
以下來自與《More Effective C++》 ,讀了覺得很有收獲
文尾有我看VS2019的MSVC2017中的頭文件 和 osg的
但是有一件我們做不到的事情是“發現靈巧指針為 NULL”:
SmartPtr<TreeNode> ptn;
if (ptn == 0) ... // error!
if (ptn) ... // error!
if (!ptn) ... // error!
這是一個嚴重的限制。
在靈巧指針類里加入一個 isNull 成員函數是一件很容易的事
但是沒有解決當測試NULL 時靈巧指針的行為與 dumb pointer(即普通指針) 不相似的問題。
另一種方法是提供隱式類型轉換操作符,允許編譯上述的測試。一般應用於這種目的的類型轉換是 void* :
template<class T>
class SmartPtr {
public:
...
operator void*(); // 如果靈巧指針為 null,
... // 返回 0, 否則返回
}; // 非 0。
SmartPtr<TreeNode> ptn;
...
if (ptn == 0) ... // 現在正確
if (ptn) ... // 也正確
if (!ptn) ... // 正確
這與 iostream 類中提供的類型轉換相同,所以可以這樣編寫代碼:
ifstream inputFile("datafile.dat");
if (inputFile) ... // 測試 inputFile 是否已經被
// 成功地打開。
像所有的類型轉換函數一樣,它有一個缺點:在一些情況下雖然大多數程序員希望它調
用失敗,但是函數確實能夠成功地被調用(參見條款 M5)。特別是它允許靈巧指針與完全不
同的類型之間進行比較:
SmartPtr<Apple> pa;
SmartPtr<Orange> po;
...
if (pa == po) ... // 這能夠被成功編譯!
即使在 SmartPtr
因為靈巧指針被隱式地轉換為 void
指針,而對於內建指針類型有內建的比較函數。這種進
行隱式類型轉換的行為特性很危險。(再回看一下條款 M5,必須反反復復地閱讀,做到耳熟
能詳。)
在 void類型轉換方面,也有一些變化。有些設計者采用到 const void*的類型轉換,
還有一些采取轉換到 bool 的方法。這些變化都沒有消除混合類型比較的問題。
有一種兩全之策可以提供合理的測試 null 值的語法形式,同時把不同類型的靈巧指針
之間進行比較的可能性降到最低。
這就是在靈巧指針類中重載 operator!,當且僅當靈巧指針是一個空指針時,operator!返回 true:
template<class T>
class SmartPtr {
public: ...
bool operator!() const; // 當且僅當靈巧指針是
... // 空值,返回 true。
};
用戶程序如下所示:
SmartPtr<TreeNode> ptn;
...
if (!ptn) { // 正確
... // ptn 是空值
}
else {
... // ptn 不是空值
}
但是這樣就不正確了:
if (ptn == 0) ... // 仍然錯誤
if (ptn) ... // 也是錯誤的
僅在這種情況下會存在不同類型之間進行比較:
SmartPtr<Apple> pa;
SmartPtr<Orange> po;
...
if (!pa == !po) ... // 能夠編譯
幸好程序員不會經常這樣編寫代碼。
有趣的是,iostream 庫的實現除了提供 void隱式
的類型轉換,也有 operator!函數,不過這兩個函數通常測試的流狀態有些不同。
(在 C++類庫標准中(參見 Effective C++ 條款 49 和本書條款 M35)
,void*隱式的類型轉換已經被bool 類型的轉換所替代,operator bool 總是返回與 operator!相反的值。)
而在osg中也有重載operator!
圖片不貼了