C++服务器开发100个知识要点C++RAII惯用法

2023-05-16

  • 最初的写法 
     在笔者刚学习服务器开发的时候,公司给笔者安排了一个练习:在 Windows 系统上写一个 C++程序,用该程序实现一个简单的服务,在客户端连接上来时,给客户端发一条“HelloWorld”消息后关闭连接,不用保证客户端一定能收到。 
     如果熟悉基础网络编程知识,那么你会觉得这很容易,因为这个程序描述的就是TCP网络通信的基本流程,其程序实现流程如下。 
     (1)创建socket。 
     (2)绑定IP地址和端口号。 
     (3)在该 IP 地址和端口号上启动监听,循环等待客户端连接的到来,在客户端连接成功后,向其发送一条“HelloWorld”消息,然后断开连接。 
     在 Windows 上使用网络通信 API 之前,需要使用 WSAStartup 函数初始化socket库;在程序结束时需要使用WSACleanup函数清理socket库。 
     笔者很快就将程序写出来了:

 

 

 

 

 版本2:使用goto语句 
 还是以前面网络通信的代码为例,如果使用goto语句,则该代码可以简化如下:

 

 

 使用 goto 语句后,一旦某个中间步骤出错,则跳转到统一的清理点进行资源清理操作。 
 但是,我们总被告知要慎用goto语句,因为它会让程序的结构变得混乱和难以维护。姑且不论这是否正确,如果不用 goto 语句,那么有没有更好的实现方式呢?有,使用do...while(0)循环。 
 1.1.3 版本3:使用do...while(0)循环 
 以上代码使用do...while(0)循环改进后如下:

 

 

 以上代码利用 do...while(0)循环中的 break 特性巧妙地将资源回收操作集中到一个地方,使用 for 循环也能达到同样的效果。我们同样可以使用 do...while(0)改造上面堆内存分配与释放的示例,伪代码如下:

 

 

 

 这是do...while(0)的一个妙用。但是,在C++中有更好的写法来代替do...while(0),即RAII惯用法。 
 1.1.4 版本4:使用RAII惯用法 
 RAII(Resource Acquisition Is Initialization,资源获取就是初始化)指资源在我们拿到时就已经初始化,一旦不再需要该资源,就可以自动释放该资源。 
 对于 C++来说,资源在构造函数中初始化(可以在构造函数中调用单独的初始化函数),在析构函数中释放或清理。常见的情形就是在函数调用中创建C++对象时分配资源,在 C++对象出了作用域时将其自动清理和释放(不管这个对象是如何出作用域的,不管是否因为某个中间步骤不满足条件而导致提前返回,也不管是否正常走完全部流程后返回)。 
 还是以上面网络通信的例子来说,初始化程序时需要分配两种资源:Windows 的socket网络库和一个用于监听的socket。首先,初始化好Windows socket网络库;然后创建一个用于监听的socket。在程序结束时,我们需要清理这两种资源。 
 使用RAII惯用法改进后的代码如下:

 

 

以上代码并没有在构造函数中分配资源,而是单独使用一个DoInit方法初始化资源,并在析构函数中回收相应的资源。这样在main函数中就不用担心任何中间步骤失败而忘记释放资源了,因为一旦main函数调用结束,serverSocket对象就会自动调用其析构函数回收相应的资源。这就是RAII惯用法的原理! 
 严格来说,以上代码中ServerSocket的成员变量m_bInit应该被设计成类静态成员,调用 WSAStartup 和 WSACleanup 的函数应该被设计成类的静态方法,因为它们只需在程序初始化和退出时各调用一次就可以了。 
 希望读者能理解 RAII 惯用法,因为它在 C++中太常用了。我们也可以使用 RAII 惯用法再次改写上文中分配堆内存的伪代码示例: 

 

 其中,heapObj对象一旦出了其作用域,该程序就会自动调用其析构函数释放堆内存。当然,RAII 惯用法中对资源分配和释放的定义可以延伸出各种外延和内涵,例如对多线程锁的获取和释放。我们在实际开发中也常常遇到以下情形:

 

 这是一段很常见的逻辑:为了避免死锁,我们必须在每个可能退出的分支上都释放锁。随着逻辑写得越来越复杂,我们忘记在某个退出的分支上释放锁的可能性也越来越大。而RAII惯用法正好解决了这个问题:我们可以将锁包裹成一个对象,在构造函数中获取锁,在析构函数中释放锁。伪代码如下:

 使用 RAII 惯用法之后,我们就再也不必在每个函数出口处都加上释放锁的代码了,因为在函数调用结束后会自动释放锁。 
 对于以上代码,有经验的读者可能一眼就看出来了:这不就是C++11中std::lock_guard和 boost 库中 boost::mutex::scoped_lock 的实现原理吗?确实是,本书后续章节会详细介绍操作系统和C++11提供的各类锁的用法。

 1.1.5 小结 
 资源泄露和死锁等问题具有非常强的隐蔽性,如果在生产环境中出现这些问题,则难以复现、排查和定位问题。理解并熟练使用RAII惯用法不仅能让我们的代码更加简洁和模块化,也能让我们在开发阶段避免一部分资源泄漏和死锁问题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++服务器开发100个知识要点C++RAII惯用法 的相关文章

随机推荐

  • 手把手教你使用--常用模块--HC05蓝牙模块,无线蓝牙串口透传模块,(实例:手机蓝牙控制STM32单片机点亮LED灯)

    最近在学STM32 xff0c 基本的学完了 xff0c 想学几个模块来巩固一下知识 xff0c 就想到了蓝牙模块 玩啥好难过有很多博客教怎么连的 xff0c 但自己看起来还是有点糊涂 模块的原理和知识点我就不讲解了 xff0c 这里我主要
  • FreeRTOS实时操作系统----机制

    四 机制 目录 四 机制 4 1任务优先级 4 1 1高优先级抢占低优先级 4 1 2时间片 4 2任务调度器 4 3临界段的保护 4 4空闲任务与阻塞延时 4 5任务延时列表 4 6消息队列 4 6 1消息队列的基本概念 4 6 2消息队
  • 三极管导通条件

    NPN三极管 xff0c 箭头朝外 xff1a 高电平导通 PNP三极管 xff0c 箭头朝里 xff1a 低电平导通
  • 74HC1G66模拟开关,多路复用

    SEL为低电平的时候 xff0c SD导通 SEL为高电平的时候 xff0c SD不导通 直接看数据手册
  • 一张图了解MOS管导通条件

    不管他长什么样 xff0c 直接就看箭头指向 箭头向栅极 xff0c 就是nmos管 xff0c 高电平导通 箭头向外 xff0c 就是pmos管 xff0c 低电平导通 一边连了两根线的就是s极
  • Android SDK的安装配置

    SDK xff1a xff08 software development kit xff09 软件开发工具包 被软件开发工程师用于为特定的软件包 软件框架 硬件平台 操作系统等建立应用软件的开发工具的集合 因此 xff0c Android
  • 1.C++简介

    学习目标 xff1a 初识C 43 43 xff0c 介绍C 43 43 一些简单的语法 xff1a 初识C 43 43 数据类型 运算符 程序流程结构 学习内容 xff1a 1 初识C 43 43 一个简单的C 43 43 框架 xff0
  • 死锁形成的原因和四个必要条件

    死锁的概念 死锁是指两个或两个以上的进程 xff08 线程 xff09 在运行过程中因争夺资源而造成的一种僵局 xff0c 若无外力作用 xff0c 这些进程 xff08 线程 xff09 都将无法向前推进 xff0c 这时就形成了死锁 处
  • Android P阻止调用非sdk api后,Atlas该何去何从

    0 背景 自从Android 9 0后 xff0c Android就已经开始着手阻止app开发调用非sdk的api xff0c 也就是被标记为 64 hide的变量 函数 类不可以通过反射调用 xff0c 否则会提示NoSuchMethod
  • 简历应该这么写!

    很多同学刚开始找工作时 xff0c 投出去很多简历 xff0c 但是都石沉大海了 xff0c 没有后文 之所以简历不通过 xff0c 往往都是简历不够 好看 很多大公司HR经常一天要看几百份 xff0c 甚至上千份简历 xff0c 基本都是
  • 希望计算机专业同学都知道这些老师

    C语言教程 翁凯老师 赫斌 翁恺老师是土生土长的浙大码农 xff0c 从本科到博士都毕业于浙大计算机系 xff0c 后来留校教书 xff0c 一教就是20多年 翁恺老师的c语言课程非常好 xff0c 讲解特别有趣 xff0c 很适合初学者学
  • 100个python算法超详细讲解:抓交通肇事犯

    1 xff0e 问题描述 一辆卡车违反交通规则 xff0c 撞人后逃跑 现场有三人目 该事件 xff0c 但都 没有记住车号 xff0c 只记下了车号的一些特征 说 xff1a 牌照的前两位数字是相 同的 xff1b 乙说 xff1a 牌照
  • 100个python算法超详细讲解:百钱百鸡

    1 xff0e 问题描述 中国古代数学家张丘建在他的 算经 中提出了一个著名的 百钱 百鸡问题 xff1a 一只公鸡值五钱 xff0c 一只母鸡值三钱 xff0c 三只小鸡值一钱 xff0c 现 在要用百钱买百鸡 xff0c 请问公鸡 母鸡
  • 100个python算法超详细讲解:水仙花数

    1 xff0e 问题描述 输出所有的 水仙花数 所谓的 水仙花数 是指一个三位数 xff0c 其各位数字的立方 和等于该数本身 xff0c 例如 xff0c 153是 水仙花数 xff0c 因为153 61 1 3 43 1 3 43 3
  • 100个python算法超详细讲解:常胜将军

    100个python算法超详细讲解 64 谷歌学术 1 xff0e 问题描述 有火柴21根 xff0c 两人依次取 xff0c 每次每人只可取走1 xff5e 4根 xff0c 不能多取 xff0c 也不能不取 xff0c 谁取到最后一根火
  • 100个python算法超详细讲解:逆序输出数字

    100个python算法超详细讲解 64 谷哥技术 1 xff0e 问题描述 编程实现将输入的整数逆序输出 2 xff0e 问题分析 前面我们已经接触过很多的递归问题了 xff0c 这些递归问题可以简单 地分成两类 xff1a 一类可以归结
  • 100个python算法超详细讲解:角谷猜想

    1 xff0e 问题描述 角谷猜想在西方常被称为西拉古斯猜想 xff0c 据说这个问题首先是在 美国的西拉古斯大学被研究的 xff0c 而在东方 xff0c 这个问题则由将它带到日 本的日本数学家角谷静夫的名字来命名 xff0c 故被称为角
  • 100个python算法超详细讲解:统计学生成绩

    完整版下载 超详细Python算法案例讲解100例 zip Python文档类资源 CSDN下载 1 xff0e 问题描述 有5个学生 xff0c 每个学生有三门课程的成绩需要统计 要求从键盘输入学生的学号 姓名以及三门课程 的成绩 xff
  • apt update、apt upgrade 和 apt dist-upgrade 的区别

    1 root 64 kali apt update apt update 的作用是从 etc apt sources list文件中定义的源中获取的最新的软件包列表 即运行 apt update 并没有更新软件 xff0c 而是相当 win
  • C++服务器开发100个知识要点C++RAII惯用法

    最初的写法 在笔者刚学习服务器开发的时候 xff0c 公司给笔者安排了一个练习 xff1a 在 Windows 系统上写一个 C 43 43 程序 xff0c 用该程序实现一个简单的服务 xff0c 在客户端连接上来时 xff0c 给客户端