defer 关键字在 C/C++ 上的实现方案

defer 关键字在 C/C++ 上的实现方案

前述:

golang 的关键字 defer 给出了一种,延时调用(RAII)的方式来释放资源。但是对于C/C++却没有内置这种方便的关键字。对于经常需要手动管理内存的C/C++尤其是C程序员这种特性显得无比重要。

这里给出了一种 C/C++ 下模拟实现 defer 的实现方案:

针对 C 语言基于 GCC/Clang 编译器扩展属性cleanup实现

针对 C++ 利用 RAII 来实现

头文件如下:(我只对 C/C++ 在 Linux 平台下 GCC/CLANG 编译器做了测试)

#ifndef __SCOPEGUARD_H__

#define __SCOPEGUARD_H__

#define __SCOPEGUARD_HELPER_IMPL(s1, s2) s1##_##s2

#define __SCOPEGUARD_HELPER(s1, s2) __SCOPEGUARD_HELPER_IMPL(s1, s2)

#if defined(__cplusplus)

#include

// ScopeGuard for C++11

namespace NSScopeGuard

{

template

class ScopeGuard

{

public:

ScopeGuard(Fun &&f) : _fun(std::forward(f)), _active(true) {}

~ScopeGuard()

{

if (_active)

_fun();

}

void dismiss() { _active = false; }

ScopeGuard() = delete;

ScopeGuard(const ScopeGuard &) = delete;

ScopeGuard &operator=(const ScopeGuard &) = delete;

ScopeGuard(ScopeGuard &&rhs) : _fun(std::move(rhs._fun)), _active(rhs._active) { rhs.dismiss(); }

private:

Fun _fun;

bool _active;

};

enum class ScopeGuardEnumHelper

{

};

template

inline ScopeGuard operator+(ScopeGuardEnumHelper, Fun &&fn)

{

return ScopeGuard(std::forward(fn));

}

} // namespace NSScopeGuard

// Helper macro

#define ON_SCOPT_EXIT \

auto __SCOPEGUARD_HELPER(RAII_AT_EXIT, __LINE__) = NSScopeGuard::ScopeGuardEnumHelper() + [&]()

#elif (defined(__linux__) || defined(__ANDROID__)) && !defined(__llvm__)

/**

* Linux(HOST) GCC does not support extension 'blocks' and keyword '__strong'

* So, just use cleanup in plain way

*/

#define ON_SCOPT_EXIT(expr) \

void __SCOPEGUARD_HELPER(RAII_AT_EXIT, __LINE__)() { expr; } \

int __USELESS_VAR __attribute__((cleanup(__SCOPEGUARD_HELPER(RAII_AT_EXIT, __LINE__))));

#else

#error "platform not support!"

#endif

#endif //__SCOPEGUARD_H__

测试:

不需要过多的解释,直接看执行结果就知道了。当超出作用域(break,goto,return)之后,会自动调用指定的内存释放函数(当然这里也可以用其他函数来代替)。()

C++:

#include

#include

#include "scopeguard.h"

using namespace std;

int main()

{

string *as = new string("hello world!");

ON_SCOPT_EXIT

{

cout << "in scope guard" << endl;

delete as;

};

cout << "at end" << endl;

return 0;

}

$ c++ xx.c

$ ./a.out

at end

in scope guard

C:

#include

int main(int argc, char **argv)

{

{

ON_SCOPT_EXIT(

printf("call defern");

);

printf("will quit scopen");

}

printf("before returnn");

return 0;

}

$ cc xx.c

$ ./a.out

will quit scope

call defer

before return

需要注意的是这里DEFER 宏展开后会发现,这里发生了函数的嵌套定义,经测试Clang 不支持函数嵌套定义,应次在头文件添加了对 llvm Clang独有编译器宏的判断。

此上C代码不能在安装Clang的Linux下编译(OSX不在此考虑范围,参考头文件__APPLE__宏)

参考:

https://zhuanlan.zhihu.com/p/21303431

https://zhuanlan.zhihu.com/p/35191739

相关文章

优易erp怎么样
office365

优易erp怎么样

📅 06-27 👀 7067
旅游攻略导航
365277

旅游攻略导航

📅 06-29 👀 8887