首页 > 编程知识 正文

充分使用英语怎么说,充分使用的成语

时间:2023-05-04 14:23:32 阅读:264217 作者:1333

一、C++ 资源管理

写代码时经常会碰到这种情况:在函数开始时申请了buffer、或打开了某文件、打开某so,需要在函数返回前做对应的释放或关闭操作。不使用任何语言机制的情况下,写出来的代码是这样的:

void before() { uint8_t *a = new uint8_t[10]; double *b = new double(1.2); if (xxx) { delete[] a; delete b; return; } if (xxx) { delete[] a; delete b; return; } delete[] a; delete b;}

在任意一个函数出口,都要进行资源释放,代码丑陋、可读性差,而且还容易出现某代码块抛异常直接退出但资源没有释放的情况。

在C++中已经内置了管理内存的RAII类,即智能指针,直接用即可。需要注意两点:

如果资源不需要被共享,出函数之前就需要释放,则优先用unique_ptr如果是申请数组,unique_ptr提供了对数组的特化,但shared_ptr直到c++17才支持对数组的特化。没有条件用较新编译器的时候需要自己写deleter c++11/14的写法1:shared_ptr<int> a(new int[10], default_delete<int[]>());c++11/14的写法2:shared_ptr<int> a(new int[10], [](int *p) {delete[] p;});c++17的写法:shared_ptr<int[]> a(new int[10]);void after() { unique_ptr<uint8_t[]> a(new uint8_t[10]); unique_ptr<double> b(new double(1.2)); if (xxx) { return; } if (xxx) { return; }} 二、利用栈变量的析构函数

除了资源管理外,如果需要在函数返回前执行某个操作,也可以使用RAII,将对应的操作放到栈变量的析构函数中去,由编译器自动为我们做这件事。

举例,需要在函数结束前将函数执行的结果错误码通过一个notify函数传递出去:

void before() { int ret = 0; if (xxx) { ret = -1; notify(ret); return; } if (xxx) { ret = -2; notify(ret); return; } notify(ret);}

改造后:

void after1() { int ret = 0; class RAIIHelper { public: explicit RAIIHelper(int &r) : mRet(r) {} ~RAIIHelper() { notify(mRet); } private: int &mRet; //传引用 } helper(ret); if (xxx) { ret = -1; return; } if (xxx) { ret = -2; return; }}

但是这样写可扩展性不好,这个RAIIHelper类只能在当前函数中用,在其他情况下不一定适用。

go语言中有一个特性叫defer——延迟执行,虽然C++中没有这玩意,但是我们可以用lambda表达式和function造一个出来。很简单,把需要执行的操作直接传进来,在析构函数中执行。

class Defer {public: explicit Defer(function<void()> f) : m_func(move(f)) {} ~Defer() { m_func(); }private: function<void()> m_func;};

再次改造后,十分清爽:

void after2() { int ret = 0; Defer defer([&ret]() { notify(ret); }); //引用捕获 if (xxx) { ret = -1; return; } if (xxx) { ret = -2; return; }}

 

三、goto

C语言举例:

void before() { uint8_t *a = malloc(10); uint8_t *b = malloc(5); if (xxx) { free(a); free(b); return; } if (xxx) { free(a); free(b); return; } free(a); free(b);}

在C中由于没有类这个概念,没法在析构函数中写入一些操作,可以用goto方式来搞:

void after1() { uint8_t *a = malloc(10); uint8_t *b = malloc(5); if (xxx) { goto End; } if (xxx) { goto End; }End: free(a); free(b);} 四、do while(0)大法

相对goto来说我更喜欢用do while(0)大法。在每个出口处加上break,然后在最后执行一次必要的资源释放等操作:

void after2() { uint8_t *a = malloc(10); uint8_t *b = malloc(5); do { if (xxx) { break; } if (xxx) { break; } } while(0); free(a); free(b);}

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。