C++模拟Java C#的 finally
在 Java 和 C# 中,finally
是一个与异常处理(try-catch
)配合使用的关键字,用于确保一段代码无论是否发生异常都会被执行。它通常用于释放资源(如文件句柄、数据库连接、锁等),避免内存泄漏或状态不一致。
C++ 没有直接的 finally
关键字,但可以通过以下几种方式实现类似的功能,确保资源释放或清理代码无论是否发生异常都会执行:
例如:
/// <summary>
/// 模拟Java C#中的Finally,用法:
/// Finally f([](){
/// std::cout << "最后执行的代码。\n";
/// });
/// 注意:不能这样用:
/// Finally([](){
/// std::cout << "会马上执行的代码。\n";
/// }
/// 用法2:
/// auto n = [] { std::cout << "执行代码。\n"; };///
/// finally f(std::move(n));
/// 最好在函数声明变量后,同时声明 Finally对象。
/// </summary>
/// 创建时间:2024-08-13 最后一次修改时间:2025-04-20
template <typename Fun>
class finally {
private:Fun _f;
public:finally() = delete;finally(const finally&) = delete;/// <summary>/// 5. 总结/// 方法 行为 适用场景/// _f(f) 总是拷贝 简单情况,但低效/// _f(std::move(f)) 强制移动 确定要移动时/// _f(std::forward<F>(f)) 完美转发 泛型代码(推荐)/// 关键点/// std::move:强制转成右值(用于移动语义)。/// /// std::forward:保持值类别(用于泛型编程,完美转发)。/// /// 在模板构造函数或工厂函数中,优先使用 std::forward 实现最高效的参数传递。/// </summary>/// <typeparam name="F"></typeparam>/// <param name="f"></param> finally(Fun&& f) : _f(std::forward<Fun>(f)) {}~finally() { _f(); }
};
例子1:
int main(int argc, char* argv[])
{ auto* p = new int(10);_Finally f([]() {delete[] p;std::cout << "资源释放\n";});//..............................}
输出:
_Finally时候非常有用,因为你在处理问题时可能遇到一个函数几百行
代码,有非常多的返回分支,如果不用_Finally,每个返回分支都可能
要小心加上恢复控制状态的代码, 例如,QTextEdit的键盘事件,
QTreeWidget鼠标事件等等。
m_tree->blockSignals(true); //临时阻止树型控件发错信号lf::_Finally f([this]() { m_tree->blockSignals(false); //允许发错信号});