std::experimental::scope_exit
来自cppreference.com
< cpp | experimental
在标头 <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: 抛出异常 是 退出状态 待定
[编辑] 参阅
包装函数对象并在通过异常退出作用域时调用 (类模板) | |
包装函数对象并在正常退出作用域时调用 (类模板) | |
(C++11) |
unique_ptr 的默认删除器 (类模板) |