复杂的东西写多了,如今写点简单的好了。由于功能上的需要, Vczh Library++3.0 被我搞得很离谱。为了开发维护的遍历、减少粗心犯下的错误以及增强单元测试、回归测试和测试工具,因此记录下一些开发上的小技巧,以便抛砖引玉,造福他人。欢迎高手来喷,菜鸟膜拜。

C++实谓各种语言中的软肋,功能强大,陷阱更强大。当然我认为一门语言用得不好完全是程序员的责任,不过因为C++涉及到的概念实在是太多,想用好实在也不是一件容易的事情。C++开发的时候总是会遇到各种各样的问题,其中最严重的无非是内存相关的。C语言由于结构简单,内存处理起来虽然不得力,但总的来说惯用法已经深入人心,因此也不会造成什么很难发现的错误。C++就不一样了。有了虚函数、构造函数、析构函数、复制构造函数和operator=重载之后,还是有很多人喜欢把一个类直接写进文件流,或者拿来memset,代码一团乱麻,不知悔改也。但是不能因此因噎废食,就像某人因为C++带来的心智问题太多,自己搞不定,自己团队也搞不定,就说C++不好一样。

因此第一篇文章主要针对内存来讲。我们处理内存,第一件事就是不要有内存泄露。内存泄露不能等到测试的时候,通过长时间运行程序并观察任务管理器的方法来做,这显然已经晚了。幸好Visual C++给了我们一个十分好用的工具:_CrtDumpMemoryLeaks函数。这个函数会在Debug模式下往Visual Studio的output窗口打印出那个时候你new(malloc)了但是还没delete(free)的所有内存块的地址、长度、前N个字节的内容和其他信息。怎么做呢?其实很简单:

 1 #define _CRTDBG_MAP_ALLOC
 2 #include <stdlib.h>
 3 #include <crtdbg.h>
 4 #include <windows.h>
 5 
 6 int wmain(vint argc , wchar_t* args[])
 7 {
 8     // 这里运行程序,并在下面的函数调用之前delete掉所有new的东西
 9     _CrtDumpMemoryLeaks();
10     return 0;
11 }

我们只需要在注释的地方完成我们程序的功能,然后确信自己已经delete掉所有应该delete的东西,最后_CrtDumpMemoryLeaks()函数调用的时候就可以打印出没被delete的东西了。这个方法十分神奇,因为你只需要在main函数所在的cpp文件这么#include一下,所有的cpp文件里面的new都会受到监视,跟平常所用的用宏把new给换掉的这种破方法截然不同。如果你使用了全局变量的话也要小心,因为全局变量的析构函数是在main函数结束之后才执行的,因此如果在全局变量的析构函数里面delete的东西仍然会被_CrtDumpMemoryLeaks函数当成泄露掉的资源对待。当然本人认为全局变量可以用,但是全局变量的赋值必须在main里面做,释放也是,除非那个全局变量的构造函数没有申请任何内存,所以这也是一个很好的检查方法。

不过上面也仅仅是一个告诉你有没有内存泄漏的方法罢了。那么如何避免内存泄露呢?当然在设计一些性能要求没有比操作系统更加严格的程序的时候,可以使用以下方法:
    1、如果构造函数new了一个对象 并使用成员指针变量 保存的话,那么必须在析构函数delete它,并且不能有为了某些便利而将这个对象的所有权转让出去的事情发生。
    2、在能使用shared_ptr的时候,尽量使用shared_ptr。shared_ptr只要你不发生循环引用,那么这个东西可以安全地互相传递、随便你放在什么容器里面添加删除、你想放哪里就放在哪里,再也不用考虑这个对象的生命周期问题了。
    3、不要在有构造函数和析构函数的对象上使用memset(或者memcpy)。如果一个对象需要memset,那么在该对象的构造函数里面memset自己。如果你需要memset一个对象数组,那也在该对象的构造函数里面memset自己。 如果你需要memset一个没有构造函数的复杂对象,那么请为他添加一个构造函数,除非那是别人的API提供的东西
    4、如果一个对象是继承了其他东西,或者某些成员被标记了virtual的话,绝对不要memset。对象是独立的,也就是说父类内部结构的演变不需要对子类负责。哪天父类里面加了一个string成员,被子类一memset,就欲哭无泪了。
    5、如果需要为一个对象定义构造函数,那么连复制构造函数、operator=重载和析构函数都全部写全。如果不想写复制构造函数和operator=的话,那么用一个空的实现写在private里面,确保任何试图调用这些函数的代码都出现编译错误。
    6、如果你实在很喜欢C语言的话,那麻烦换一个只支持C不支持C++的编译器,全面杜绝因为误用了C++而导致你的C坏掉的情况出现。

什么是循环引用呢?如果两个对象互相使用一个shared_ptr成员变量直接或者间接指向对方的话,就是循环引用了。在这种情况下引用计数会失效,因为就算外边的shared_ptr全释放光了,引用计数也不会是0的。

今天就说到这里了,过几天我高兴的话再写一篇续集,如果我持续高兴的话呢……嗯嗯……。

from: 复杂的东西写多了,如今写点简单的好了。由于功能上的需要,Vczh Library++3.0被我搞得很离谱。为了开发维护的遍历、减少粗心犯下的错误以及增强单元测试、回归测试和测试工具,因此记录下一些开发上的小技巧,以便抛砖引玉,造福他人。欢迎高手来喷,菜鸟膜拜。

C++实谓各种语言中的软肋,功能强大,陷阱更强大。当然我认为一门语言用得不好完全是程序员的责任,不过因为C++涉及到的概念实在是太多,想用好实在也不是一件容易的事情。C++开发的时候总是会遇到各种各样的问题,其中最严重的无非是内存相关的。C语言由于结构简单,内存处理起来虽然不得力,但总的来说惯用法已经深入人心,因此也不会造成什么很难发现的错误。C++就不一样了。有了虚函数、构造函数、析构函数、复制构造函数和operator=重载之后,还是有很多人喜欢把一个类直接写进文件流,或者拿来memset,代码一团乱麻,不知悔改也。但是不能因此因噎废食,就像某人因为C++带来的心智问题太多,自己搞不定,自己团队也搞不定,就说C++不好一样。

因此第一篇文章主要针对内存来讲。我们处理内存,第一件事就是不要有内存泄露。内存泄露不能等到测试的时候,通过长时间运行程序并观察任务管理器的方法来做,这显然已经晚了。幸好Visual C++给了我们一个十分好用的工具:_CrtDumpMemoryLeaks函数。这个函数会在Debug模式下往Visual Studio的output窗口打印出那个时候你new(malloc)了但是还没delete(free)的所有内存块的地址、长度、前N个字节的内容和其他信息。怎么做呢?其实很简单:

 1 #define _CRTDBG_MAP_ALLOC
 2 #include <stdlib.h>
 3 #include <crtdbg.h>
 4 #include <windows.h>
 5 
 6 int wmain(vint argc , wchar_t* args[])
 7 {
 8     // 这里运行程序,并在下面的函数调用之前delete掉所有new的东西
 9     _CrtDumpMemoryLeaks();
10     return 0;
11 }

我们只需要在注释的地方完成我们程序的功能,然后确信自己已经delete掉所有应该delete的东西,最后_CrtDumpMemoryLeaks()函数调用的时候就可以打印出没被delete的东西了。这个方法十分神奇,因为你只需要在main函数所在的cpp文件这么#include一下,所有的cpp文件里面的new都会受到监视,跟平常所用的用宏把new给换掉的这种破方法截然不同。如果你使用了全局变量的话也要小心,因为全局变量的析构函数是在main函数结束之后才执行的,因此如果在全局变量的析构函数里面delete的东西仍然会被_CrtDumpMemoryLeaks函数当成泄露掉的资源对待。当然本人认为全局变量可以用,但是全局变量的赋值必须在main里面做,释放也是,除非那个全局变量的构造函数没有申请任何内存,所以这也是一个很好的检查方法。

不过上面也仅仅是一个告诉你有没有内存泄漏的方法罢了。那么如何避免内存泄露呢?当然在设计一些性能要求没有比操作系统更加严格的程序的时候,可以使用以下方法:
    1、如果构造函数new了一个对象 并使用成员指针变量 保存的话,那么必须在析构函数delete它,并且不能有为了某些便利而将这个对象的所有权转让出去的事情发生。
    2、在能使用shared_ptr的时候,尽量使用shared_ptr。shared_ptr只要你不发生循环引用,那么这个东西可以安全地互相传递、随便你放在什么容器里面添加删除、你想放哪里就放在哪里,再也不用考虑这个对象的生命周期问题了。
    3、不要在有构造函数和析构函数的对象上使用memset(或者memcpy)。如果一个对象需要memset,那么在该对象的构造函数里面memset自己。如果你需要memset一个对象数组,那也在该对象的构造函数里面memset自己。 如果你需要memset一个没有构造函数的复杂对象,那么请为他添加一个构造函数,除非那是别人的API提供的东西
    4、如果一个对象是继承了其他东西,或者某些成员被标记了virtual的话,绝对不要memset。对象是独立的,也就是说父类内部结构的演变不需要对子类负责。哪天父类里面加了一个string成员,被子类一memset,就欲哭无泪了。
    5、如果需要为一个对象定义构造函数,那么连复制构造函数、operator=重载和析构函数都全部写全。如果不想写复制构造函数和operator=的话,那么用一个空的实现写在private里面,确保任何试图调用这些函数的代码都出现编译错误。
    6、如果你实在很喜欢C语言的话,那麻烦换一个只支持C不支持C++的编译器,全面杜绝因为误用了C++而导致你的C坏掉的情况出现。

什么是循环引用呢?如果两个对象互相使用一个shared_ptr成员变量直接或者间接指向对方的话,就是循环引用了。在这种情况下引用计数会失效,因为就算外边的shared_ptr全释放光了,引用计数也不会是0的。

今天就说到这里了,过几天我高兴的话再写一篇续集,如果我持续高兴的话呢……嗯嗯……。

C++实用技巧(一)相关推荐

  1. 深度学习11个实用技巧

    深度学习11个实用技巧 深度学习工程师George Seif发表了一篇博文,总结了7个深度学习的技巧,本文增加了几个技巧,总结了11个深度学习的技巧,主要从提高深度学习模型的准确性和速度两个角度来分析 ...

  2. 【老鸟分享】Linux命令行终端提示符多种实用技巧!

    1.Linux命令行提示符简介 众所周知,Linux命令行是系统管理员管理Linux的重要手段,我们管理Linux,首先要面对的就是Linux命令行提示符. Linux命令行结尾的提示符有" ...

  3. 经典 | 深度学习的7大实用技巧

    编译 | AI科技大本营 参与 | 林椿眄 编辑 | 谷 磊 对于许多具有挑战性的现实问题,深度学习已经成为最有效的解决方法. 例如,对于目标检测,语音识别和语言翻译等问题,深度学习能够表现出最佳的性 ...

  4. 深度学习七个实用技巧

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 深度学习已经成为解决许多具有挑战性的现实世界问题的方法.对目标检测 ...

  5. Python大神用的贼溜,9个实用技巧分享给你

    来源:数据分析1480 本文约3000字,建议阅读6分钟 本文为你介绍一些关于python的实用技巧. 本文会试着介绍一些其它文章没有提到的小技巧,这些小技巧也是我平时会用到的的.让我们一探究竟吧! ...

  6. 5 个针对有经验用户的 Vim 实用技巧

    Vim 编辑器提供了很多的特性,要想全部掌握它们很困难.然而,花费更多的时间在命令行编辑器上总是有帮助的.毫无疑问,和 Vim 用户们进行交流能够让你更快地学习新颖有创造性的东西. 注: 本文中用到的 ...

  7. ES6的几个实用技巧,你了解吗?

    本文给大家分享了es6的几个实用技巧,非常不错,具有参考借鉴价值,感兴趣的朋友一起学习吧 Hack #1 交换元素 利用 数组解构来实现值的互换 let a = 'world', b = 'hello ...

  8. 在此处打开命令窗口_这样操作方便多了!简单DOS命令实用技巧详解

    分享简单DOS命令实用技巧,让我们的工作.生活更加方便快捷.小编致力于分享分享智能数码.弱电组网.电脑软硬件资讯及实用技巧. 先跟着小编一起来了解一下DOS命令是一个什么样子的存在?技术大牛,请忽略, ...

  9. Windows2003实用技巧

    Windows2003实用技巧七则 一.跳过磁盘检修等待时间 一旦计算机因意外原因,例如突然停电或者死机的话,那么计算机下次重新启动的话,系统就会花10秒钟左右的时间,来运行磁盘扫描程序,检查磁盘是否 ...

  10. jexcel可以合并单元格么_含金量超高的3个文本、字符合并实用技巧解读!

    当各位亲看到此篇文章时,说明已是2019年1月1日呢,感谢各位亲对小编的支持和厚爱,在这里祝福各位亲元旦快乐,"19"快乐,事业有成--同时,小编会继续努力为各位亲开发更多的实用技 ...

最新文章

  1. Java架构师笔记-你必须掌握学习Java需要掌握哪些技能
  2. 第三讲:WCF介绍(3)
  3. Java troubleshooting guide
  4. Happy Number 十进制转特殊三进制
  5. 工作158:vue里面为什么要加key
  6. 管理端口_内网渗透 | 红蓝对抗:Windows利用WinRM实现端口复用打造隐蔽后门
  7. Exceptions, Catch, and Throw(Chapter 10 of Programming Ruby)
  8. Gnumeric,专业处理数字软件
  9. HTML5之语义化标签
  10. mysql中的concat和group_concat的用法
  11. Unity3D用户手册翻译(与Unity3D圣典同步)—— 优化手机的实用指南 - 未来及高端设备...
  12. 计算机设置成一个网络,怎样将笔记本电脑设置成一个wifi热点
  13. vue3项目简化Compositions API使用-省去频繁的import和各use函数调用
  14. vue FullCalendar使用案例及详解
  15. 如何 拆 贴片电容 而不是把焊盘给搞坏
  16. input自动填充后背景颜色被覆盖的问题
  17. spring系列——BeanNameGenerator接口(bean名字生成器)
  18. Legacy引导转UEFI引导(BIOS、Legacy引导、UEFI引导、GPT/MBR分区)
  19. 删除压缩包密码的方式有几种?
  20. LightRoom教程——Lr预设如何导入xmp文件?

热门文章

  1. mysql服务重启后不见了_一次诡异的Mysql服务不断重启故障排查
  2. 深入理解分布式技术 - 分布式锁的应用场景和主流方案
  3. MySQL - 高效的设计MySQL库表
  4. 实战SSM_O2O商铺_33【商品】商品编辑之Service层的实现
  5. LAN交换机自学习算法
  6. css控制边界与边框示例(内边距、外边距使用方法)
  7. python里countsget_在Python中测试访问同一数据的竞争条件的方法
  8. python 文本分析库_Python有趣|中文文本情感分析
  9. java单态模式_Java单态模式
  10. java 64位 默认分配内存大小_查看你机器中Java程序堆内存的默认初始大小和最大大小...