更多 C++ 慣用法/函式中毒
外觀
隱藏或禁止使用某些函式,支援更好的替代方案。
通常,在與具有 C 或 C++11 前介面的庫互動時,由於現代 C++ 表達能力更強,因此隱藏(對正在專案中工作的人員來說)所有(或僅僅是許多)分配記憶體並返回原始指標(如 T*)的函式,並用更友好的 RAII 方法(如 unique_ptr)替換它們非常方便。
// header of external library
foo* create_foo();
foo_destroy(foo*);
// our header, with our enhanced version
struct foo_deleter {
void operator()(foo* h) {
// foo_destroy provided by the 3rd party library as function, macro, ...
foo_destroy(h);
}
};
using unique_foo = std::unique_ptr<foo, foo_deleter>;
inline unique_foo create_unique_foo() {
// we do not have poisoned create_foo yet!
return unique_foo{create_foo()};
}
#pragma GCC poison create_foo
// from now on, no-one can use create_foo again!
// at least with GCC and clang
禁止函式的指南
如果函式 g 是庫 L 中函式 f 的嚴格替換,那麼
g提供了比f更明顯的優勢(例如將解構函式中的析構器替換為手動呼叫)g可以作為f的直接替換,這意味著- 它可以在不編寫多於一行沒有明顯缺點的粘合程式碼的情況下與庫 L 互動
- 在程式碼庫中將
f更新為g是一個簡單的操作(使用更改所有出現或簡單的查詢和替換) - 刪除
f的成本不太高
g與f相比沒有任何缺點,這意味著- 它與
f相比沒有新增任何可衡量的執行時開銷 - 它沒有新增任何新的依賴項
- 它不能降低型別安全性、異常安全性或執行緒安全性
- 它不能引入新的程式設計錯誤型別
- 它與
g與f相比不會降低可讀性或隱藏意圖,這意味著- 不需要記錄
g的作用,因為它應該與f一樣,只有在那些對每個人都不清楚的情況下才需要記錄其優點。
- 不需要記錄
因此,如果 g 是 f 的嚴格替換,那麼可以在程式碼庫中禁止 f。
用具有改進功能的函式替換不能刪除的函式(例如,如果它是外部庫的一部分)。