高质量C++/C编程指南(七)内存管理

目录

一、内存的分配方式

二、常见的内存错误及其对策

三、指针参数是如何传递内存的?

1、如果非得要用指针参数去申请内存,那么应该用“指向指针的指针”。

2、用函数返回值来传递动态内存

四、free和delete把指针怎么啦?

五、动态内存会被自动释放吗?

六、杜绝“野指针'

七、内存耗尽怎么办?

八、malloc/free的使用要点

1、malloc

2、free

九、new/delete的使用要点

1、new

2、delete

十、一些心得体会


一、内存的分配方式

内存分配方式有三种:

  1. 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static 变量。
  2. 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
  3. 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。
     

二、常见的内存错误及其对策

常见的内存错误及其对策如下:
内存分配未成功,却使用了它。
        编程新手常犯这种错误,因为他们没有意识到内存分配会不成功。常用解决办法是,在使用内存之前检查指针是否为NULL。如果指针p是函数的参数,那么在函数的入口处用assert (p!=NULL)进行检查。如果是用malloc或new来申请内存,应该用if(p==NULL)或if(p!=NULL)进行防错处理
● 内存分配虽然成功,但是尚未初始化就引用它。
       犯这种错误主要有两个起因:一是没有初始化的观念;二是误以为内存的缺省初值全为零,导致引用初值错误(例如数组)。内存的缺省初值究竟是什么并没有统一的标准,尽管有些时候为零值,我们宁可信其无不可信其有。所以无论用何种方式创建数组,都别忘了赋初值,即便是赋零值也不可省略,不要嫌麻烦。
● 内存分配成功并且已经初始化,但操作越过了内存的边界。
       例如在使用数组时经常发生下标“多1”或者“少1”的操作。特别是在for循环语句中,循环次数很容易搞错,导致数组操作越界。

● 忘记了释放内存,造成内存泄露。
       含有这种错误的函数每被调用一次就丢失一块内存。刚开始时系统的内存充足,你看不到错误。终有一次程序突然死掉,系统出现提示:内存耗尽。
       动态内存的申请与释放必须配对,程序中malloc与free的使用次数一定要相同,否则肯定有错误(new/delete 同理)。

● 释放了内存却继续使用它。
有三种情况:
(1) 程序中的对象调用关系过于复杂,实在难以搞清楚某个对象究竟是否已经释放了内存,此时应该重新设计数据结构,从根本上解决对象管理的混乱局面。
(2) 函数的return语句写错了,注意不要返回指向“栈内存”的“指针”或者“引用”,因为该内存在函数体结束时被自动销毁。
(3) 使用free或delete释放了内存后,没有将指针设置为NULL。 导致产生“野指针”。


[规则7-2-1]  用malloc或new申请内存之后,应该立即检查指针值是否为NULL。防止使用指针值为NULL的内存
[规则7-2-2]  不要忘记为数组和动态内存赋初值。防止将未被初始化的内存作为右值使用。
[规则7-2-3]  避免数组或指针的下标越界,特别要当心发生“多1”或者“少1”操作。
[规则7-2-4]  动态内存的申请与释放必须配对,防止内存泄漏。
[规则7-2-5]  用free或delete释放了内存之后,立即将指针设置为NULL,防止产生“野指针”

三、指针参数是如何传递内存的?

1、如果非得要用指针参数去申请内存,那么应该用“指向指针的指针”。

2、用函数返回值来传递动态内存

 

四、free和delete把指针怎么啦?

别看free和delete的名字恶狠狠的(尤其是delete),它们只是把指针所指的内存给释放掉,但并没有把指针本身干掉。在使用free和delete后,我们要把该指针赋值为NULL

五、动态内存会被自动释放吗?

函数体内的局部变量在函数结束时自动消亡。很多人误以为下图是正确的。

(1) 指针消亡了,并不表示它所指的内存会被自动释放。
(2) 内存被释放了,并不表示指针会消亡或者成了NULL指针。

六、杜绝“野指针'

       “野指针”不是NULL指针,是指向“垃圾”内存的指针。人们一般不会错用NULL指针,因为用if语句很容易判断。但是“野指针”是很危险的,if语句对它不起作用
(1)指针变量没有被初始化。

         

(2)指针p被free或者delete之后,没有置为NULL,让人误以为p是个合法的指针。

(3)指针操作超越了变量的作用范围。

七、内存耗尽怎么办?

       如果在申请动态内存时找不到足够大的内存块,malloc和new将返回NULL指针,宣告内存申请失败。通常有三种方式处理“内存耗尽”问题。
(1)判断指针是否为NULL,如果是则马上用return语句终止本函数。
(2)判断指针是否为NULL,如果是则马上用exit(1)终止整个程序的运行。

八、malloc/free的使用要点

1、malloc

函数malloc的原型如下:void * malloc(size_t size);用malloc申请一块长度为length的整数类型的内存,程序如下:

int *p = (int *) malloc(sizeof(int) * length) ;
我们应当把注意力集中在两个要素上:“类型转换” 和“sizeof”。
● malloc 返回值的类型是void *,所以在调用malloc时要显式地进行类型转换,将void*转换成所需要的指针类型
● malloc函数本身并不识别要申请的内存是什么类型,它只关心内存的总字节数。在malloc的“()”中使用sizeof运算符是良好的风格。

2、free

函数free的原型如下:void free( void * memblock ) ;
       为什么free函数不像malloc函数那样复杂呢?

       这是因为指针p的类型以及它所指的内存的容量事先都是知道的,语句free (p)能正确地释放内存。如果p是NULL指针,那么free对p无论操作多少次都不会出问题。如果p不是NULL指针,那么free对p连续操作两次就会导致程序运行错误。

九、new/delete的使用要点

1、new

运算符new使用起来要比函数malloc简单得多,例如:

因为new内置了sizeof、类型转换和类型安全检查功能。

2、delete

在用delete释放对象数组时,留意不要丢了符号‘[]’,例如

十、一些心得体会

(1)越是怕指针,就越要使用指针。不会正确使用指针,肯定算不上是合格的程序员。
(2)必须养成“使用调试器逐步跟踪程序”的习惯,只有这样才能发现问题的本质。

 

已标记关键词 清除标记
目 录 前 言6 第1 章 文件结构 1.1 版权和版本的声明. 1.2 头文件的结构. 1.3 定义文件的结构. 1.4 头文件的作用. 1.5 目录结构. 第2 章 程序的版式 2.1 空行. 2.2 代码行. 2.3 代码行内的空格. 2.4 对齐. 2.5 长行拆分. 2.6 修饰符的位置. 2.7 注释. 2.8 类的版式. 第3 章 命名规则 3.1 共性规则. 3.2 简单的WINDOWS 应用程序命名规则. 3.3 简单的UNIX 应用程序命名规则 第4 章 表达式和基本语句 4.1 运算符的优先级. 4.2 复合表达式. 4.3 IF 语句 4.4 循环语句的效率. 4.5 FOR 语句的循环控制变量. 4.6 SWITCH 语句. 4.7 GOTO 语句. 第5 章 常量 5.1 为什么需要常量. 5.2 CONST 与 #DEFINE 的比较. 5.3 常量定义规则. 5.4 类中的常量. 第6 章 函数设计 高质量C++/C 编程指南,v 1.0 2001 Page 4 of 101 6.1 参数的规则. 6.2 返回值的规则. 6.3 函数内部实现的规则. 6.4 其它建议. 6.5 使用断言. 6.6 引用与指针的比较. 第7 章 内存管理 7.1 内存分配方式 7.2 常见的内存错误及其对策 7.3 指针与数组的对比 7.4 指针参数是如何传递内存的? 7.5 FREE 和DELETE 把指针怎么啦? 7.6 动态内存会被自动释放吗?. 7.7 杜绝“野指针”. 7.8 有了MALLOC/FREE 为什么还要NEW/DELETE ?. 7.9 内存耗尽怎么办?. 7.10 MALLOC/FREE 的使用要点 7.11 NEW/DELETE 的使用要点. 7.12 一些心得体会 第8 章 C++函数的高级特性 8.1 函数重载的概念. 8.2 成员函数的重载、覆盖与隐藏. 8.3 参数的缺省值. 8.4 运算符重载. 8.5 函数内联. 8.6 一些心得体会. 第9 章 类的构造函数、析构函数与赋值函数 9.1 构造函数与析构函数的起源. 9.2 构造函数的初始化表. 9.3 构造和析构的次序. 9.4 示例:类STRING 的构造函数与析构函数 9.5 不要轻视拷贝构造函数与赋值函数. 9.6 示例:类STRING 的拷贝构造函数与赋值函数 9.7 偷懒的办法处理拷贝构造函数与赋值函数. 9.8 如何在派生类中实现类的基本函数. 9.9 一些心得体会. 第10 章 类的继承与组合. 高质量C++/C 编程指南,v 1.0 2001 Page 5 of 101 10.1 继承 10.2 组合 第11 章 其它编程经验. 11.1 使用CONST 提高函数的健壮性 11.2 提高程序的效率 11.3 一些有益的建议 参考文献 附录A :C++/C 代码审查表. 附录B :C++/C 试题. 附录CC++/C 试题的答案与评分标准.
相关推荐
林锐 博士 CHM电子书 目 录 前 言 6 第1章 文件结构 11 1.1 版权和版本的声明 11 1.2 头文件的结构 12 1.3 定义文件的结构 13 1.4 头文件的作用 13 1.5 目录结构 14 第2章 程序的版式 15 2.1 空行 15 2.2 代码行 16 2.3 代码行内的空格 17 2.4 对齐 18 2.5 长行拆分 19 2.6 修饰符的位置 19 2.7 注释 20 2.8 类的版式 21 第3章 命名规则 22 3.1 共性规则 22 3.2 简单的WINDOWS应用程序命名规则 23 3.3 简单的UNIX应用程序命名规则 25 第4章 表达式和基本语句 26 4.1 运算符的优先级 26 4.2 复合表达式 27 4.3 IF 语句 27 4.4 循环语句的效率 29 4.5 FOR 语句的循环控制变量 30 4.6 SWITCH语句 30 4.7 GOTO语句 31 第5章 常量 33 5.1 为什么需要常量 33 5.2 CONST 与 #DEFINE的比较 33 5.3 常量定义规则 33 5.4 类中的常量 34 第6章 函数设计 36 6.1 参数的规则 36 6.2 返回值的规则 37 6.3 函数内部实现的规则 39 6.4 其它建议 40 6.5 使用断言 41 6.6 引用与指针的比较 42 第7章 内存管理 44 7.1内存分配方式 44 7.2常见的内存错误及其对策 44 7.3指针与数组的对比 45 7.4指针参数是如何传递内存的? 47 7.5 FREE和DELETE把指针怎么啦? 50 7.6 动态内存会被自动释放吗? 50 7.7 杜绝“野指针” 51 7.8 有了MALLOC/FREE为什么还要NEW/DELETE ? 52 7.9 内存耗尽怎么办? 53 7.10 MALLOC/FREE 的使用要点 54 7.11 NEW/DELETE 的使用要点 55 7.12 一些心得体会 56 第8章 C++函数的高级特性 57 8.1 函数重载的概念 57 8.2 成员函数的重载、覆盖与隐藏 60 8.3 参数的缺省值 63 8.4 运算符重载 64 8.5 函数内联 65 8.6 一些心得体会 68 第9章 类的构造函数、析构函数与赋值函数 69 9.1 构造函数与析构函数的起源 69 9.2 构造函数的初始化表 70 9.3 构造和析构的次序 72 9.4 示例:类STRING的构造函数与析构函数 72 9.5 不要轻视拷贝构造函数与赋值函数 73 9.6 示例:类STRING的拷贝构造函数与赋值函数 73 9.7 偷懒的办法处理拷贝构造函数与赋值函数 75 9.8 如何在派生类中实现类的基本函数 75 9.9 一些心得体会 77 第10章 类的继承与组合 78 10.1 继承 78 10.2 组合 80 第11章 其它编程经验 82 11.1 使用CONST提高函数的健壮性 82 11.2 提高程序的效率 84 11.3 一些有益的建议 85 参考文献 87 附录A :C++/C代码审查表 88 附录B :C++/C试题 93 附录CC++/C试题的答案与评分标准 97
内容简介回到顶部↑高质量软件开发是国内计算机教育的薄弱环节,很多程序员虽然能熟练地掌握编程技术但是缺乏强烈的质量意识,不懂得在开发过程中内建高质量。这使得大部分企业只能依靠大量地测试和改错来提高软件产品的质量,为此付出了高昂的代价。因此,如何有效地提高软件产品的质量是IT企业面临的主要挑战之一。 本书论述高质量软件开发方法与C++/C编程规范共十五章,分两部分: 第一部分共四章,重点介绍软件质量和面向对象程序设计方法。 第二部分共十一章,重点阐述C++/C编程风格和一些技术专题。 本书以幽默的笔调对软件工程和编程作了很好的论述。前期版本曾经在Internet上广泛流传,被国内IT企业的不少软件开发人员采用。 本书的主要读者对象是IT企业的程序员和项目经理,以及高年级本科生和研究生。 目录回到顶部↑第一部分 综述 第1章 高质量软件开发之道 第2章 做好程序员 第3章 编程语言发展简史 第4章 面向对象程序设计方法概述 第二部分 C++/C编程规范 第5章 文件结构 第6章 程序的版式 第7章 命名规则 第8章 表达式与基本语句 第9章 常量 第10章 函数设计 第11章 内存管理 第12章 C++函数的高级特性 第13章 类的构造函数、析构函数与赋值函数 第14章 C++ STL应用 第15章 其它编程经验 参考文献及评注 第三部分 附录 附录 A:C++/C 试题
DirectX修复工具(DirectX Repair)是一款系统级工具软件,简便易用。本程序为绿色版,无需安装,可直接运行。 本程序的主要功能是检测当前系统的DirectX状态,如果发现异常则进行修复。程序主要针对0xc000007b问题设计,可以完美修复该问题。本程序中包含了最新版的DirectX redist(Jun2010),并且全部DX文件都有Microsoft的数字签名,安全放心。 本程序为了应对一般电脑用户的使用,采用了易用的一键式设计,只要点击主界面上的“检测并修复”按钮,程序就会自动完成校验、检测、下载、修复以及注册的全部功能,无需用户的介入,大大降低了使用难度。在常规修复过程中,程序还会自动检测DirectX加速状态,在异常时给予用户相应提示。 本程序适用于多个操作系统,如Windows XP(需先安装.NET 2.0,详情请参阅“致Windows XP用户.txt”文件)、Windows Vista、Windows 7、Windows 8、Windows 8.1、Windows 8.1 Update、Windows 10,同时兼容32位操作系统和64位操作系统。本程序会根据系统的不同,自动调整任务模式,无需用户进行设置。 本程序的V4.0版分为标准版、增强版以及在线修复版。所有版本都支持修复DirectX的功能,而增强版则额外支持修复c++的功能。在线修复版功能与标准版相同,但其所需的数据包需要在修复时自动下载。各个版本之间,主程序完全相同,只是其配套使用的数据包不同。因此,标准版和在线修复版可以通过补全扩展包的形式成为增强版。本程序自V3.5版起,自带扩展功能。只要在主界面的“工具”菜单下打开“选项”对话框,找到“扩展”标签,点击其中的“开始扩展”按钮即可。扩展过程需要Internet连接,扩展成功后新的数据包可自动生效。扩展用时根据网络速度不同而不同,最快仅需数秒,最慢需要数分钟,烦请耐心等待。如扩展失败,可点击“扩展”界面左上角小锁图标切换为加密连接,即可很大程度上避免因防火墙或其他原因导致的连接失败。 本程序自V2.0版起采用全新的底层程序架构,使用了异步多线程编程技术,使得检测、下载、修复单独进行,互不干扰,快速如飞。新程序更改了自我校验方式,因此使用新版本的程序时不会再出现自我校验失败的错误;但并非取消自我校验,因此程序安全性与之前版本相同,并未降低。 程序有更新系统c++功能。由于绝大多数软件运行时需要c++的支持,并且c++的异常也会导致0xc000007b错误,因此程序在检测修复的同时,也会根据需要更新系统中的c++组件。自V3.2版本开始使用了全新的c++扩展包,可以大幅提高工业软件修复成功的概率。修复c++的功能仅限于增强版,标准版及在线修复版在系统c++异常时(非丢失时)会提示用户使用增强版进行修复。除常规修复外,新版程序还支持C++强力修复功能。当常规修复无效时,可以到本程序的选项界面内开启强力修复功能,可大幅提高修复成功率。请注意,请仅在常规修复无效时再使用此功能。 程序有两种窗口样式。正常模式即默认样式,适合绝大多数用户使用。另有一种简约模式,此时窗口将只显示最基本的内容,修复会自动进行,修复完成10秒钟后会自动退出。该窗口样式可以使修复工作变得更加简单快速,同时方便其他软件、游戏将本程序内嵌,即可进行无需人工参与的快速修复。开启简约模式的方法是:打开程序所在目录下的“Settings.ini”文件(如果没有可以自己创建),将其中的“FormStyle”一项的值改为“Simple”并保存即可。 新版程序支持命令行运行模式。在命令行中调用本程序,可以在路径后直接添加命令进行相应的设置。常见的命令有7类,分别是设置语言的命令、设置窗口模式的命令,设置安全级别的命令、开启强力修复的命令、设置c++修复模式的命令、控制Direct加速的命令、显示版权信息的命令。具体命令名称可以通过“/help”或“/?”进行查询。 程序有高级筛选功能,开启该功能后用户可以自主选择要修复的文件,避免了其他不必要的修复工作。同时,也支持通过文件进行辅助筛选,只要在程序目录下建立“Filter.dat”文件,其中的每一行写一个需要修复文件的序号即可。该功能仅针对高级用户使用,并且必须在正常窗口模式下才有效(简约模式时无效)。 本程序有自动记录日志功能,可以记录每一次检测修复结果,方便在出现问题时,及时分析和查找原因,以便找到解决办法。 程序的“选项”对话框中包含了7项高级功能。点击"常规”选项卡可以调整程序的基本运行情况,包括日志记录、安全级别控制、调试模式开启等。只有开启调试模式后才能在C
<p> <span style="color:#337FE5;"><strong>【为什么还需要学习C++?】</strong></span> </p> <p style="margin-left:0cm;"> 你是否接触很多语言,但从来没有了解过编程语言的本质? </p> <p style="margin-left:0cm;text-align:start;"> 你是否想成为一名资深开发人员,想开发别人做不了的高性能程序? </p> <p style="margin-left:0cm;text-align:start;"> 你是否经常想要窥探大型企业级开发工程的思路,但苦于没有基础只能望洋兴叹? </p> <p style="margin-left:0cm;text-align:start;">   </p> <p style="margin-left:0cm;text-align:start;"> 那么C++就是你个人能力提升,职业之路进阶的不二之选。 </p> <p style="margin-left:0cm;text-align:start;"> <br /> </p> <p style="margin-left:0cm;text-align:start;"> <br /> </p> <p style="margin-left:0cm;"> <strong><span style="color:#337FE5;">【课程特色】</span></strong> </p> <p style="margin-left:0cm;text-align:start;"> 1.课程共19大章节,239课时内容,涵盖数据结构、函数、类、指针、标准库全部知识体系。 </p> <p style="margin-left:0cm;text-align:start;"> 2.带你从知识与思想的层面从0构建C++知识框架,分析大型项目实践思路,为你打下坚实的基础。 </p> <p style="margin-left:0cm;text-align:start;"> 3.李宁老师结合4大国外顶级C++著作的精华为大家推出的《征服C++11》课程。 </p> <p style="margin-left:0cm;text-align:start;"> <br /> </p> <p class="ql-long-24357476"> <span style="color:#337FE5;"><strong>【学完后我将达到什么水平?】</strong></span> </p> <p class="ql-long-24357476"> 1.对C++的各个知识能够熟练配置、开发、部署; </p> <p class="ql-long-24357476"> 2.吊打一切关于C++的笔试面试题; </p> <p class="ql-long-24357476"> 3.面向物联网的“嵌入式”和面向大型化的“分布式”开发,掌握职业钥匙,把握行业先机。 </p> <p class="MsoNoSpacing" style="margin-left:18pt;"> <br /> </p> <div> <br /> </div> <p> <br /> </p> <p style="margin-left:0cm;text-align:start;"> <span style="color:#337FE5;"><strong>【面向人群】</strong></span> </p> <p style="margin-left:0cm;text-align:start;"> <span style="color:#222226;font-family:PingFangSC-Regular, "font-size:14px;background-color:#FFFFFF;">1.希望一站式快速入门的C++初学者;</span> </p> <p style="margin-left:0cm;text-align:start;"> <span style="color:#222226;font-family:PingFangSC-Regular, "font-size:14px;background-color:#FFFFFF;">2.希望快速学习 C++、掌握编程要义、修炼内功的开发者;</span> </p> <p style="margin-left:0cm;text-align:start;"> <span style="color:#222226;font-family:PingFangSC-Regular, "font-size:14px;background-color:#FFFFFF;">3.有志于挑战更高级的开发项目,成为资深开发的工程师。</span> </p> <p style="margin-left:0cm;text-align:start;"> <br /> </p> <p> <br /> </p> <p> <span style="color:#337FE5;"><strong>【课程设计】</strong></span> </p> <p> 本课程包含3大模块 </p> <p> <strong>基础篇</strong><br /> 本篇主要讲解c++的基础概念,包含数据类型、运算符等基本语法,数组、指针、字符串等基本词法,循环、函数、类等基本句法等。 </p> <p> <br /> <strong>进阶篇</strong><br /> 本篇主要讲解编程中常用的一些技能,包含类的高级技术、类的继承、编译链接和命名空间等。 </p> <p> <br /> <strong>提升篇:</strong><br /> 本篇可以帮助学员更加高效的进行c++开发,其中包含类型转换、文件操作、异常处理、代码重用等内容。 </p> <p> <img src="https://img-bss.csdnimg.cn/202007091130239667.png" alt="" /> </p>
<span style="color:#E53333;"><span style="color:#000000;"> </span></span> <p style="font-size:16px;"> <span style="color:#3A4151;">课程演示环境:Ubuntu </span> </p> <p style="font-size:16px;"> </p><p> <span><span style="color:#0070C0;">需要学习Windows系统YOLOv4的同学请前往《Windows版YOLOv4目标检测实战:人脸口罩佩戴检测》</span></span> </p> <p> <span><span style="color:#0070C0;">课程链接:https://edu.csdn.net/course/detail/29123</span></span>  </p> <p style="font-size:16px;"> <span style="background-color:#FFFFFF;">当前,人脸口罩佩戴检测是急需的应用,而YOLOv4是最新的强悍的目标检测技术。本课程使用</span><strong><span style="color:#C00000;">YOLOv4实现实时的人脸口罩佩戴检测</span></strong><span style="background-color:#FFFFFF;">。课程提供</span><strong><span style="color:#C00000;">超万张已标注人脸口罩数据集</span></strong><span style="background-color:#FFFFFF;">。训练后的YOLOv4可对真实场景下人脸口罩佩戴进行</span><span style="background-color:#FFFFFF;">高精度地</span><span style="background-color:#FFFFFF;">实时检测。</span> </p> <p style="font-size:16px;"> <span style="background-color:#FFFFFF;"><br /></span> </p> <p style="font-size:16px;"> <span><span style="background-color:#FFFFFF;"><span style="font-size:16px;">本课程会讲述本项目超万张人脸口罩数据集的制作方法,包括使用labelImg标注工具标注以及如何使用Python代码对第三方数据集进行修复和清洗。</span><br /></span></span> </p> <p style="font-size:16px;"> <span><span style="background-color:#FFFFFF;"><br /></span></span> </p> <p style="font-size:16px;"> 本课程的YOLOv4使用AlexyAB/darknet,在Ubuntu系统上做项目演示。具体项目过程包括:安装YOLOv4、训练集和测试集自动划分、修改配置文件、训练网络模型、测试训练出的网络模型、性能统计(mAP计算和画出PR曲线)和先验框聚类分析。  </p> <p style="font-size:16px;"> <br /></p> <p style="font-size:16px;"> <br /></p> <p style="font-size:16px;"> <img src="https://img-bss.csdn.net/202005200601524939.jpg" alt="" /></p> <p style="font-size:16px;"> <strong>YOLOv4人脸口罩佩戴检测效果</strong> </p> <p style="font-size:16px;"> <img src="https://img-bss.csdn.net/202005200603052758.jpg" alt="" /></p> <p style="font-size:16px;"> <br /></p> <span style="color:#000000;"></span>
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页