命名空間
變體
動作

std::experimental::scope_exit

出自 cppreference.com
定義於標頭檔 <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] 參見

封裝一個函式物件,並在因異常退出作用域時呼叫它
(類別模板) [編輯]
封裝一個函數物件,並在正常離開作用域時呼叫它
(類別模板) [編輯]
unique_ptr 的預設刪除器
(類別範本) [編輯]
English Deutsch 日本語 中文(简体) 中文(繁體)