上一篇文章写了怎么构建一个类来实现RAII
但是看起来还是挺麻烦的
网上搜了一圈发现一个Scope Guard 范围守卫
一、Scope Guard 范围守卫
Scope Guard 范围守卫的典型实现是RAII习语用法增加一个条件控制
将RAII扩展,可以主动的去控制是否释放内存。
二、Scope Guard 范围守卫代码
利用Scope已经写好的宏定义,我们可以非常方便的只要一个宏就可以让我们的变量在超出作用域后自动释放内存。
Scope Guard 范围守卫 - 知乎 (zhihu.com)
代码是这篇大佬的文章里找到的,我们加入到一个头文件就行
#pragma once
#include <cstdlib>
#include <iostream>
#include <stack>
using namespace std;
namespace clover {
template <typename F>
class ScopeGuard
{
public:
explicit ScopeGuard(F&& f) : m_func(std::move(f)), m_dismiss(false)
{
}
explicit ScopeGuard(const F& f) : m_func(f), m_dismiss(false) {}
~ScopeGuard()
{
if (!m_dismiss)
m_func();
}
ScopeGuard(ScopeGuard&& rhs) :
m_func(std::move(rhs.m_func)), m_dismiss(rhs.m_dismiss) {
rhs.dismiss();
}
ScopeGuard() = delete;
ScopeGuard(const ScopeGuard&) = delete;
ScopeGuard& operator=(const ScopeGuard&) = delete;
void dismiss()
{
m_dismiss = true;
}
private:
F m_func;
bool m_dismiss;
};
namespace detail {
enum class ScopeGuardOnExit {};
template <typename Fun>
inline ScopeGuard<Fun> operator+(ScopeGuardOnExit, Fun&& fn) {
return ScopeGuard<Fun>(std::forward<Fun>(fn));
}
} // namespace detail
} // namespace clover
#define __SCOPEGUARD_CONCATENATE_IMPL(s1, s2) s1##s2
#define __SCOPEGUARD_CONCATENATE(s1, s2) __SCOPEGUARD_CONCATENATE_IMPL(s1, s2)
#define ON_SCOPE_EXIT \
auto __SCOPEGUARD_CONCATENATE(ext_exitBlock_, __LINE__) = clover::detail::ScopeGuardOnExit() + [&]()
#define ON_SCOPE_EXIT_WITH_RETURN \
clover::detail::ScopeGuardOnExit() + [&]()
在我们的项目里引入这个头文件。
然后在需要自动释放的变量后加上宏定义就行
// 打开输入文件
if (avformat_open_input(&inputFormatContext, inputFile.c_str(), nullptr, nullptr) != 0) {
std::cout << "无法打开输入文件" << std::endl;
return false;
}
ON_SCOPE_EXIT{ avformat_close_input(&inputFormatContext); };
这上面的就是使用ON_SCOPE_EXIT定义来自动释放我们生成的inputFormatContext变量,在出现异常或者是离开作用域的时候都会自动释放空间。