std::experimental::scope_exit
来自 cppreference.cn
定义于头文件 <experimental/scope> |
||
template< class EF > class scope_exit; |
(库基础 TS v3) | |
类模板 scope_exit
是一个通用的作用域守卫,旨在当作用域退出时调用其退出函数。
scope_exit
不是可复制构造的(CopyConstructible)、可复制赋值的(CopyAssignable)或可移动赋值的(MoveAssignable),但是,如果 EF
满足某些要求,它可能是可移动构造的(MoveConstructible),这允许将 scope_exit
封装到另一个对象中。
一个 scope_exit
可以是活动的(active),即在销毁时调用其退出函数,也可以是不活动的(inactive),即在销毁时什么也不做。从退出函数构造后,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 << " 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
[编辑] 另见
封装一个函数对象并在通过异常退出作用域时调用它 (类模板) | |
封装一个函数对象并在正常退出作用域时调用它 (类模板) | |
(C++11) |
unique_ptr 的默认删除器 (类模板) |