百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

C++ RAII 来自实战的分享

liebian365 2025-02-13 13:00 6 浏览 0 评论

先看一个例子

#include 

int main() {
	// 申请内存
	char *p = new char[4096];

	// 。。。。。。。。。
	// 这里省略了N行业务代码
	// 。。。。。。。。。

	// 释放内存
	delete[] p;

	return 0;
}

以上操作方式存在的隐患:


  • 1. 可能由于中间业务代码太长,后面的delete[] p;会忘记;
  • 2. 即使有后面的delete[] p;但是中间业务代码如果出现异常,比如数组访问越界等,那么将会导致最后的delete无法运行,内存得不到释放,程序运行久了之后将会内存溢出(服务器内存被撑爆或达到程序最大可使用的内存后被kill掉)。

怎么避免?RAII,它就是用来解决上述问题的。


我个人认为,随着RAII的提出,现代C++(C11以及之后)库大量采用RAII方式进行编写,现在已经是使用C++进行程序编写的最佳时机,可以兼顾高性能和高安全性。

RAII的定义


来自百科的定义:

RAII,也称为“资源获取就是初始化”,是c++用来管理资源、避免内存泄露的方法。

简单粗暴理解为:

资源获取或内存分配在构造函数中进行,释放在析构函数中进行。这样就不存在忘记释放资源或者内存,即使是程序出现异常,也能够得到安全释放。高安全、高安全、高安全、高安全(重要事情说三遍)。

对上述代码基于RAII实现

class SafeString {
private:
  char *sPtr = nullptr;
public:
  SafeString() = delete;
  SafeString(const SafeString &) = delete;
  SafeString& operator=(const SafeString &) = delete;
  
  SafeString(int size) {
    // 在构造函数初始化这里进行内存的申请
    sPtr = new char[size];
  }
  ~SafeString() {
    // 在析构函数这里进行释放
    if (sPtr != nullptr) {
      delete[] sPtr;
      sPtr = nullptr;
    }
  }
  // 这里获取到字符串操作的指针,方便外部
  char* getStrPtr() {return sPtr;}
};

int main() {
  // 进行访问控制
  SafeString sPtr(4096);

  // 。。。。。。
  // 这里省略了N行业务代码
  // 。。。。。。

  return 0;
}

个人项目案例背景


并发访问控制:

注册手机号不能重复问题:由于用户账号表支持手机号、邮箱、微信、。。。。。等方式进行注册,所以数据表不能对手机号字段设定唯一索引,为了避免一个手机号注册存在多条记录,采用Redis的set nx技术进行控制。

示例代码如下

class UtilViewGuard {
private:
  string mViewKey;
  bool mCanView;
public:
  UtilViewGuard() = delete;
  // 这里的viewKey对应案例分析就是phone号码
  // 因为还可以适用于其它场景,所以这里用viewKey
  UtilViewGuard(std::string viewKey) {
    mViewKey = viewKey;
    mCanView = false;
    string viewValue;
    // 设定60秒也会自动过期,多重保障
    int ex = 60;
    redisCommand(
      // 这里假设hiRedis已经被正确的初始化
      // 关于hiRedis的使用,可以看我之前分享
      hiRedis, 
      // 这里的核心是nx,也就是key不存在才会设定
      // 这样同一个时间就只会有一个手机号码可以注册
      "set %s %s ex %d nx",
      mViewKey.c_str(), viewValue.c_str(), ex
    );
    // 这里根据操作结果是否成功对mCanView进行赋值
    // 限于篇幅,这里省略
  }
  ~UtilAccessGuard() {
    // 在析构中进行删除,这样操作完成,用户有可以尝试注册了
    // 当然这里尝试注册会失败,哈哈哈,主要是一个思想
    redisCommand(hiRedis, "del %s", mViewKey.c_str());
  }
  // 是否可以访问
  bool canView() {return mCanView;}
};

int main() {
  // 。。。。。。
  // 这里假设对用户请求做了初步检查
  // 。。。。。。

  // 进行访问控制
  UtilViewGuard uvg;
  if (!uvg.canView()) {
    // 这里如果不能访问则直接返回
    return -1;
  }

  // 。。。。。。
  // 这里进行进行注册业务代码以及其它代码
  // 。。。。。。

  return 0;
}

交流:

大家实际项目中哪些场景下需要自己去基于C++的RAII技术实现呢?

相关推荐

4万多吨豪华游轮遇险 竟是因为这个原因……

(观察者网讯)4.7万吨豪华游轮搁浅,竟是因为油量太低?据观察者网此前报道,挪威游轮“维京天空”号上周六(23日)在挪威近海发生引擎故障搁浅。船上载有1300多人,其中28人受伤住院。经过数天的调...

“菜鸟黑客”必用兵器之“渗透测试篇二”

"菜鸟黑客"必用兵器之"渗透测试篇二"上篇文章主要针对伙伴们对"渗透测试"应该如何学习?"渗透测试"的基本流程?本篇文章继续上次的分享,接着介绍一下黑客们常用的渗透测试工具有哪些?以及用实验环境让大家...

科幻春晚丨《震动羽翼说“Hello”》两万年星间飞行,探测器对地球的最终告白

作者|藤井太洋译者|祝力新【编者按】2021年科幻春晚的最后一篇小说,来自大家喜爱的日本科幻作家藤井太洋。小说将视角放在一颗太空探测器上,延续了他一贯的浪漫风格。...

麦子陪你做作业(二):KEGG通路数据库的正确打开姿势

作者:麦子KEGG是通路数据库中最庞大的,涵盖基因组网络信息,主要注释基因的功能和调控关系。当我们选到了合适的候选分子,单变量研究也已做完,接着研究机制的时便可使用到它。你需要了解你的分子目前已有哪些...

知存科技王绍迪:突破存储墙瓶颈,详解存算一体架构优势

智东西(公众号:zhidxcom)编辑|韦世玮智东西6月5日消息,近日,在落幕不久的GTIC2021嵌入式AI创新峰会上,知存科技CEO王绍迪博士以《存算一体AI芯片:AIoT设备的算力新选择》...

每日新闻播报(September 14)_每日新闻播报英文

AnOscarstatuestandscoveredwithplasticduringpreparationsleadinguptothe87thAcademyAward...

香港新巴城巴开放实时到站数据 供科技界研发使用

中新网3月22日电据香港《明报》报道,香港特区政府致力推动智慧城市,鼓励公私营机构开放数据,以便科技界研发使用。香港运输署21日与新巴及城巴(两巴)公司签署谅解备忘录,两巴将于2019年第3季度,开...

5款不容错过的APP: Red Bull Alert,Flipagram,WifiMapper

本周有不少非常出色的app推出,鸵鸟电台做了一个小合集。亮相本周榜单的有WifiMapper's安卓版的app,其中包含了RedBull的一款新型闹钟,还有一款可爱的怪物主题益智游戏。一起来看看我...

Qt动画效果展示_qt显示图片

今天在这篇博文中,主要实践Qt动画,做一个实例来讲解Qt动画使用,其界面如下图所示(由于没有录制为gif动画图片,所以请各位下载查看效果):该程序使用应用程序单窗口,主窗口继承于QMainWindow...

如何从0到1设计实现一门自己的脚本语言

作者:dong...

三年级语文上册 仿写句子 需要的直接下载打印吧

描写秋天的好句好段1.秋天来了,山野变成了美丽的图画。苹果露出红红的脸庞,梨树挂起金黄的灯笼,高粱举起了燃烧的火把。大雁在天空一会儿写“人”字,一会儿写“一”字。2.花园里,菊花争奇斗艳,红的似火,粉...

C++|那些一看就很简洁、优雅、经典的小代码段

目录0等概率随机洗牌:1大小写转换2字符串复制...

二年级上册语文必考句子仿写,家长打印,孩子照着练

二年级上册语文必考句子仿写,家长打印,孩子照着练。具体如下:...

一年级语文上 句子专项练习(可打印)

...

亲自上阵!C++ 大佬深度“剧透”:C++26 将如何在代码生成上对抗 Rust?

...

取消回复欢迎 发表评论: