谈谈C++的ScopeExit
2020-01-27 本文已影响0人
this_is_for_u
最近研究了boost中的ScopeExit,发现是个这是个很高级的特性,可以在作用域结束时自动关闭已经打开的资源或做某些清理操作。
举例: 如果没有ScopeExit
void test () {
char *test = new char[100];
if (a) {
delete[] test; // count 1
return;
}
xxx;
if (b) {
delete[] test; // count 2
return;
}
xxx;
delete[] test; // count 3
}
使用了ScopeExit
void test () {
char *test = new char[100];
ScopeExit {
delete[] test; // 在test函数声明周期结束后自动执行delete[]操作
};
if (a) {
return;
}
xxx;
if (b) {
return;
}
xxx;
}
当然,正常C++代码不鼓励使用裸指针,可以使用智能指针来申请资源,这里只是举个例子,使用ScopeExit也可以用于处理文件资源的关闭等等。
两者代码比较后优劣程度显而易见,不使用ScopeExit需要在return前多次做资源清理操作,而使用了ScopeExit则只需做一次声明后在作用域结束后会自动进行相关的资源清理操作,方便而且不易出错。
ScopeExit实现
这里参考boost使用C++11实现了一套ScopeExit机制
class ScopeExit {
public:
ScopeExit() = default;
ScopeExit(const ScopeExit&) = delete;
void operator=(const ScopeExit&) = delete;
ScopeExit(ScopeExit&&) = default;
ScopeExit& operator=(ScopeExit&&) = default;
template <typename F, typename... Args>
ScopeExit(F&& f, Args&&... args) {
func_ = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
}
~ScopeExit() {
if (func_) {
func_();
}
};
private:
std::function<void()> func_;
};
#define _CONCAT(a, b) a##b
#define _MAKE_SCOPE_(line) ScopeExit _CONCAT(defer, line) = [&]()
#undef SCOPE_GUARD
#define SCOPE_GUARD _MAKE_SCOPE_(__LINE__)
使用方式如下:
void test () {
char *test = new char[100];
SCOPE_GUARD{
delete[] test;
};
if (a) {
return;
}
xxx;
if (b) {
return;
}
xxx;
}