這裡的Resouce不光指Memory,可能是FILE,或是ffmpeg那種Handle
Resource Management一直都是個討論的重點,要混合在C++使用,有很多種方法
拿FILE來舉例好了
什麼都不做
1 | FILE *fp = fopen(...); |
這種方法最直接,不用學其他額外的方法,不過常常會因為程式碼的改變,而忘記release resource這件事,因此才有其他流派生存的機會
defer
大概的程式碼長這樣,不過在C++不一定叫defer,可能叫ScopeGuard之類的東西,不過原理是一樣的
1 | FILE *fp = fopen(...); |
在小規模的使用是沒問題的,當Resoruce 一多就會變得冗餘,例如
1 | FILE *fp1 = fopen(...); |
於是C++ RAII的方式出現了,有鑑於shared_ptr
耗費較多的資源,這邊的方案都是unique_ptr
為主
naive unique_ptr solution
為每個resource寫出一個Wrapper
1 | struct FILEWrapper { |
沒什麼不好,只是工作量太大,每加一種Resource就要有個Wrapper,那有沒有其他方案
unique_ptr with custrom destruction
同樣以FILE舉例,新增一個function object
1 |
|
這樣看起來跟上面差不了多少
另一種方法是
1 | std::unique_ptr<FILE, int(*)(FILE *)> fp(fp, fclose); |
這種方式比上面那個還差
out_ptr
雖然跟上面無關,不過這也是unique_ptr的一部分,一併提出
由於API設計的關係,input需要的是double pointer
程式有些可能會變成這樣
1 | std::unique_ptr<ITEMIDLIST_ABSOLUTE, CoTaskMemFreeDeleter> pidl; ITEMIDLIST_ABSOLUTE* rawPidl; |
這時候就是out_ptr使用場警
1 | std::unique_ptr<ITEMIDLIST_ABSOLUTE, CoTaskMemFreeDeleter> pidl; |
雖然這是在C++23才進入標準庫,不過
GitHub - soasis/out_ptr: Repository for a C++11 implementation of std::out_ptr (p1132), as a standalone library!
已經可以先嘗鮮了
template auto
C++17之後,放寬template的要求
於是這樣的程式碼成為可能
1 | template <auto destroy> |
配合上C++20的Concept之後,成為威力強大的武器
以下是從Meeting CPP 2022中節錄出來的片段
1 | template <typename T, auto * ConstructFunction, auto * DestructFunction> |
幾乎修正了上面所說的痛點
使用上也只要
1 | c_resource<FILE, fopen, fclose> fp; |
算是目前看到最通用的解法
Coroutine solution
這算是另闢新徑的方案,RAII的方案都把release resource放在destructor中
自從C++20引進Corotuine,產生了新的可能
使用上大概會是這樣
1 | co_resource<FILE*> usage() { |