IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++中do...while(false)妙用 -> 正文阅读

[C++知识库]C++中do...while(false)妙用

C++中do…while(false)妙用

C++中,循环逻辑有三种格式:forwhile以及do...while();,前两种是比较常用的,循环逻辑也很直观,但是do...while()循环一般比较少见,它其实更多地是用在宏函数定义和代码结构优化中,具体看下面代码:

用在宏函数中

加入需要定义一个释放内存的宏函数,如下:

#define SAFE_DELETE(ptr)                                                                                               \
  delete ptr;                                                                                                          \
  ptr = nullptr;

使用场景如下:

void foo() {
  int *ptr = new int(0);
  if (ptr != nullptr)
    SAFE_DELETE(ptr);
  else {
    /* do something */
  }
  return;
}

此时,宏函数展开后的代码实际上这样的:

void foo() {
  int *ptr = new int(0);
  if (ptr != nullptr)
    delete ptr;
  ptr = nullptr;
  else {
    /* do something */
  }
  return;
}

两个问题:

  • 由于释放函数含有两条语句,只有一条语句会被if语句嵌入,从而导致else分支无法匹配到相对应的if语句,编译错误
  • 代码ptr = nullptr,不论if语句成立与否,都会被执行,偏离此代码初衷

解决办法:

在宏函数定义处,或者宏函数使用处用{}限制作用域,仍然存在两个问题:

  • 宏函数定义处,用{}包裹宏函数,那么在使用该函数且存在else分支时,宏函数使用处末尾不能加;,否则else分支仍然编译错误,但是在C++中,语句末尾加;是一种习惯
  • 在对应的if分支后,将宏函数用{}包裹,这样就避免了上述问题,而且也是提倡的编程习惯,但是这种宏函数更多的是用在库的代码中,库的的开发者不能依靠使用库的程序员有良好的编程习惯来保证宏函数的正确使用,就没有一种普适的方法么?有的,看以下代码
#define SAFE_DELETE(ptr)                                                                                               \
  do {                                                                                                                 \
    delete ptr;                                                                                                        \
    ptr = nullptr;                                                                                                     \
  } while (false)

此时,我们用do...while(false)循环将宏函数包裹,因为循环条件恒为假,循环体只会执行一次,且被包裹的循环体是被当做一条语句体来处理的,因此不会有上面所述的错误发生,在各种源码框架中,这样的用法极其普遍,算是一种奇技淫巧吧。再看第二种用法,这个也是最近在看公司项目代码时产生的疑问,所以在网上查了下,自己也总结了下。

用于非循环结构

这种用法主要是为了消除冗余代码,简化代码结构,考虑以下代码,因为在函数开始动态申请了内存,而这个内存作用域仅在函数体内,因此函数退出时需要释放这片内存,防止内存泄漏。如下代码所示,我们可以用条件语句实现这个逻辑:

bool func1();
bool func2();
bool func3();

void goo1() {
  int *ptr = new int(0); // 函数退出时需要释放该内存

  if (!func1()) {
    delete ptr;
    ptr = nullptr;
    return;
  }
  if (!func2()) {
    delete ptr;
    ptr = nullptr;
    return;
  }
  if (!func3()) {
    delete ptr;
    ptr = nullptr;
    return;
  }

  delete ptr;
  ptr = nullptr;
  return;
}

当函数执行过程中发生错误退出时,因为需要释放掉前面申请的内存,所以每次执行失败时都要去清理内存,但是代码看起来却很丑陋,很冗余,同样的代码写了四遍,C++兼容C,自然也可以使用goto语句来整理代码,如下:

void goo2() {
  int *ptr = new int(0); // 函数退出时需要释放该内存

  if (!func1())
    goto release_memory;
  if (!func2())
    goto release_memory;
  if (!func3())
    goto release_memory;

release_memory:
  delete ptr;
  ptr = nullptr;
  return;
}

将末尾的释放代码打上标签,每当函数发生错误便无条件跳转到释放内存的代码处开始执行,不失为一种很优雅的方法,但是在C++中,使用goto语句本身就是一种很敏感的行为,虽然像这样在函数体内使用是没有风险的,而且在一些库中,这样的写法也随处可见,当然了,我们也可以封装一个函数或者lambda函数去处理也是可以的,但是像这种局部性比较强的代码没必有封装一个函数,那有没有一种更为优雅的实现方式呢?看以下代码:

void goo3() {
  int *ptr = new int(0); // 函数退出时需要释放该内存

  do {
    if (!func1())
      break;
    if (!func2())
      break;
    if (!func3())
      break;
  } while (false);

  delete ptr;
  ptr = nullptr;
  return;
}

但凡函数执行过程中发生错误,循环体会立即break,函数会执行内存释放处的逻辑,对比第一个版本,不仅消除了冗余代码,而且代码结构也很清晰。当然,如果函数发生错误时,不需要做什么清理工作,也可以直接return出去的。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-12 16:25:18  更:2021-08-12 16:26:09 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/26 17:46:18-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计