作用域守卫
在退出作用域时执行清理
作用域守卫 是 CoddyKit 上的免费 C++ Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 C++ Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 C++ Academy 课程共包含 4 节课。
什么是作用域守卫
作用域守卫是一种 RAII 对象,其唯一任务是在离开作用域时执行清理操作——即使函数提前返回或抛出异常也不例外。
它解决的问题
如果没有守卫,在提前执行 return 或 throw 后很容易忘记清理。作用域守卫会让这项操作自动执行。
lock_guard:标准作用域守卫
std::lock_guard 会在构造时锁定互斥量,并在析构时解锁——它是专门用于锁的内置作用域守卫。
#include <mutex>
std::mutex m;
void critical() {
std::lock_guard<std::mutex> lk(m); // locked
// ... work ...
} // unlocked automatically手动编写守卫
您可以编写一个持有函数并在析构函数中调用它的守卫。
#include <iostream>
#include <functional>
class ScopeGuard {
std::function<void()> fn;
public:
ScopeGuard(std::function<void()> f) : fn(std::move(f)) {}
~ScopeGuard() { fn(); }
};
int main() {
ScopeGuard g([] { std::cout << "cleanup\n"; });
std::cout << "work\n";
}提前返回时执行清理
由于析构函数会在退出作用域时触发,无论函数以何种方式退出,守卫的操作都会执行。
#include <iostream>
#include <functional>
class ScopeGuard {
std::function<void()> fn;
public:
ScopeGuard(std::function<void()> f) : fn(std::move(f)) {}
~ScopeGuard() { fn(); }
};
void run(bool stop) {
ScopeGuard g([] { std::cout << "always cleaned\n"; });
if (stop) return;
}
int main() { run(true); }发生异常时执行清理
如果异常沿作用域向外传播,守卫的析构函数仍会运行,从而安全地释放资源。
取消守卫
有时您希望跳过清理(因为操作已经成功)。真正的守卫会提供 dismiss() 来禁用这项操作。
#include <iostream>
#include <functional>
class ScopeGuard {
std::function<void()> fn;
bool active = true;
public:
ScopeGuard(std::function<void()> f) : fn(std::move(f)) {}
void dismiss() { active = false; }
~ScopeGuard() { if (active) fn(); }
};
int main() {
ScopeGuard g([] { std::cout << "rollback\n"; });
g.dismiss(); // success: no rollback
}用于回滚
作用域守卫非常适合事务性代码:注册回滚操作,执行工作,然后在成功时取消守卫。
守卫只能移动
守卫不应被拷贝——拷贝会导致该操作执行两次。请让守卫只能移动或不可拷贝。
标准库和辅助工具
std::scoped_lock 可以保护多个互斥量,而 GSL 等库提供了 finally。许多代码库还会提供一个小型的 ScopeGuard 工具。
优先使用专用 RAII 类型
当存在专用的 RAII 类型时(如 lock_guard、unique_ptr、fstream),请优先使用它。只有在没有自然封装方式的临时清理场景中,才使用通用作用域守卫。
快速检查
请测试您对作用域守卫的理解。
回顾
您已经学习了作用域守卫如何通过 RAII 在退出作用域时自动执行清理。它可以处理提前返回和异常,支持通过 dismiss() 执行回滚,并且应只能移动。存在专用 RAII 类型时,请优先使用它们。
用 AI 导师学习 C++ — 免费
在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。
- 课程
- 51
- 课程
- 203
常见问题解答
「作用域守卫」课时是免费的吗?
是的 — 「作用域守卫」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C++ Academy 课程的其余内容,请升级到 CoddyKit PRO。 C++ Academy 课程共包含 4 节课。
「作用域守卫」这节课中我会学到什么?
在退出作用域时执行清理 你通过在浏览器中直接运行的动手代码来练习 C++ Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 C++ Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 C++ Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「作用域守卫」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 C++ Academy 课中编写并运行代码吗?
能。每节 C++ Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。