std::experimental::scope_exit
出自 cppreference.com
< cpp | experimental
| 定義於標頭檔 <experimental/scope> |
||
| template< class EF > class scope_exit; |
(library fundamentals TS v3) | |
類別模板 scope_exit 是一種通用目的的範圍守衛(scope guard),旨在於離開作用域時呼叫其結束函數(exit function)。
scope_exit 不具備 CopyConstructible(複製建構)、CopyAssignable(複製賦值)或 MoveAssignable(移動賦值)特性;然而,若 EF 滿足特定要求,它可能是 MoveConstructible(移動建構)的,這允許將 scope_exit 封裝到另一個物件中。
scope_exit 可以是啟用的(即在解構時呼叫其結束函數),或是停用的(即在解構時不做任何事)。scope_exit 在由結束函數建構後處於啟用狀態。
透過手動或自動(由移動建構函式)呼叫 release(),scope_exit 可以變為停用狀態。也可以透過以另一個停用的 scope_exit 進行初始化來獲得停用的 scope_exit。一旦 scope_exit 變為停用,它就無法再次變為啟用。
scope_exit 實際上持有一個 EF 以及一個用來指示其是否為啟用狀態的 bool 旗標。
目錄 |
[edit] 模板參數
| EF | - | 所儲存的結束函式類型 |
| 類型要求 | ||
-EF 必須是下列其中之一:
| ||
| -以無參數形式呼叫 std::remove_reference_t<EF> 的左值必須是良構(well-formed)的。 | ||
[edit] 成員函式
建構一個新的 scope_exit(公開成員函式) | |
若 scope_exit 處於啟用狀態,則在離開作用域時呼叫結束函數,隨後解構該 scope_exit(公開成員函式) | |
| operator= [已刪除] |
scope_exit 不可賦值(公開成員函式) |
修改器 | |
使 scope_exit 變為停用狀態(公開成員函式) | |
[編輯] 推導指引
[edit] 附註
建構具有動態儲存期的 scope_exit 可能會導致意外行為。
若 scope_exit 物件中儲存的 EF 參照了定義該物件之函數的區域變數(例如:以參照方式捕捉該變數的 lambda),且該變數被用作該函數的返回運算元,則當 scope_exit 的解構函式執行並呼叫結束函數時,該變數可能已經被返回了。這可能導致令人驚訝的行為。
[edit] 範例
執行此程式碼
#include <iostream> #include <cstdlib> #include <string_view> #include <experimental/scope> void print_exit_status(std::string_view name, bool exit_status, bool did_throw) { std::cout << name << ":\n"; std::cout << " Throwed exception " << (did_throw ? "yes" : "no") << "\n"; std::cout << " Exit status " << (exit_status ? "finished" : "pending") << "\n\n"; } // Randomly throw an exception (50% chance) void maybe_throw() { if (std::rand() >= RAND_MAX / 2) throw std::exception{}; } int main() { bool exit_status{false}, did_throw{false}; // Manual handling at "end of scope" try { maybe_throw(); exit_status = true; } catch (...) { did_throw = true; } print_exit_status("Manual handling", exit_status, did_throw); // Using scope_exit: runs on scope exit (success or exception) exit_status = did_throw = false; try { auto guard = std::experimental::scope_exit{[&]{ exit_status = true; } }; maybe_throw(); } catch (...) { did_throw = true; } print_exit_status("scope_exit", exit_status, did_throw); // Using scope_fail: runs only if an exception occurs exit_status = did_throw = false; try { auto guard = std::experimental::scope_fail{[&]{ exit_status = true; } }; maybe_throw(); } catch (...) { did_throw = true; } print_exit_status("scope_fail", exit_status, did_throw); // Using scope_success: runs only if no exception occurs exit_status = did_throw = false; try { auto guard = std::experimental::scope_success{[&]{ exit_status = true; } }; maybe_throw(); } catch (...) { did_throw = true; } print_exit_status("scope_success", exit_status, did_throw); }
輸出
Manual handling: Throwed exception yes Exit status pending scope_exit: Throwed exception no Exit status finished scope_fail: Throwed exception yes Exit status finished scope_success: Throwed exception yes Exit status pending
[edit] 參見
| 封裝一個函式物件,並在因異常退出作用域時呼叫它 (類別模板) | |
| 封裝一個函數物件,並在正常離開作用域時呼叫它 (類別模板) | |
| (C++11) |
unique_ptr 的預設刪除器 (類別範本) |