std::experimental:: scope_exit
|
定义于头文件
<experimental/scope>
|
||
|
template
<
class
EF
>
class scope_exit ; |
(库基础技术规范 v3) | |
类模板
scope_exit
是一种通用作用域守卫,旨在在退出作用域时调用其退出函数。
scope_exit
不满足
可复制构造
、
可复制赋值
或
可移动赋值
的要求,但若
EF
满足特定条件时,它可以是
可移动构造
的,这允许将
scope_exit
包装到另一个对象中。
一个
scope_exit
可以是激活状态(即在析构时调用其退出函数)或非激活状态(即在析构时不执行任何操作)。当从退出函数构造完成后,
scope_exit
处于激活状态。
一个
scope_exit
可以通过手动或自动(通过移动构造函数)调用其
release()
方法变为非活动状态。通过用另一个非活动的
scope_exit
进行初始化也可以获得非活动的
scope_exit
。一旦
scope_exit
变为非活动状态,就无法再次激活。
一个
scope_exit
实际上持有一个
EF
和一个
bool
标志位,用于指示其是否处于激活状态。
目录 |
模板参数
| EF | - | 存储退出函数的类型 |
| 类型要求 | ||
-
EF
应为以下类型之一:
|
||
|
-
|
||
成员函数
构造新的
scope_exit
(公开成员函数) |
|
若
scope_exit
处于活动状态,则在退出作用域时调用退出函数,然后销毁
scope_exit
(公开成员函数) |
|
|
operator=
[deleted]
|
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"; } // 随机抛出异常(50%概率) 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
的默认删除器
(类模板) |