std::experimental::scope_exit

来自cppreference.com
在标头 <experimental/scope> 定义
template< class EF >
class scope_exit;
(库基础 TS v3)

类模板 scope_exit 是通用的作用域防护,有意使它在退出作用域时调用其退出函数。

scope_exit可复制构造 (CopyConstructible) 可复制赋值 (CopyAssignable) 可移动赋值 (MoveAssignable) ,然而若 EF 满足某些要求则它可能为可移动构造 (MoveConstructible) ,这允许包装 scope_exit 到另一对象中。

scope_exit 可为活跃,即在析构时调用其退出函数,或为不活跃,即在析构时不做任何事。在从退出函数构造后 scope_exit 为活跃。

scope_exit 能因手动或自动(由移动构造函数)在它上调用 release() 后变得不活跃。亦可由从另一不活跃的 scope_exit 初始化获得不活跃的 scope_exit。一旦 scope_exit 不活跃,则它不能再次变得活跃。

一个 scope_exit 等效地保有一个 EF 与一个指示它是否活跃的 bool 标签。

目录

[编辑] 模板形参

EF - 退出函数的类型
类型要求
-
EF 可为:
-
以无实参调用 std::remove_reference_t<EF> 的左值必须为良构。

[编辑] 成员函数

构造新的 scope_exit
(公开成员函数) [编辑]
在退出作用域时调用退出函数,若 scope_exit 为活跃,然后销毁 scope_exit
(公开成员函数) [编辑]
operator=
[弃置]
scope_exit 不可赋值
(公开成员函数)
修改器
使 scope_exit 不活跃
(公开成员函数) [编辑]

[编辑] 推导指引

[编辑] 注解

构造拥有动态存储期的 scope_exit 可能导致非预期的行为。

若存储于 scope_exit 对象的 EF 引用到定义它的函数的局部变量,例如为按引用捕获该变量的 lambda,则在该 scope_exit 的析构函数执行并调用退出函数时该变量可能已经被返回。这能导致令人诧异的行为。

[编辑] 示例

#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 << "  抛出异常  " << (did_throw ? "是" : "否") << "\n";
  std::cout << "  退出状态  " << (exit_status ? "完成" : "待定") << "\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};
 
  // 在“作用域末尾”人工处理
  try {
    maybe_throw();
    exit_status = true; 
  } catch (...) { did_throw = true; }
  print_exit_status("人工处理", exit_status, did_throw);
 
  // 使用 scope_exit:在(成功或异常)退出作用域时执行
  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);
 
  // 使用 scope_fail:仅于发生异常时执行
  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);
 
  // 使用 scope_success:仅于未发生异常时执行
  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);
}

输出:

人工处理:
  抛出异常  是
  退出状态  待定
 
scope_exit:
  抛出异常  否
  退出状态  完成
 
scope_fail:
  抛出异常  是
  退出状态  完成
 
scope_success:
  抛出异常  是
  退出状态  待定

[编辑] 参阅

包装函数对象并在通过异常退出作用域时调用
(类模板) [编辑]
包装函数对象并在正常退出作用域时调用
(类模板) [编辑]
unique_ptr 的默认删除器
(类模板) [编辑]