1、分而治之;
2、优化工作不是可有可无的事情,而是必须要做的事情;
3、为了使整个组织具有最好的战斗力,我们要重用几个人,照顾一些人,在万不得已的情况下委屈一批人;
4、技术评审(Technical Review, TR)的目的是尽早地发现工作成果中的缺陷,并帮助开发人员及时消除缺陷,从而有效地提高产品的质量
5、测试是通过运行测试用例(Test Case)来找出软件中的缺陷。测试与技术评审的主要区别是:前者要运行软件而后者不必运行软件(动态检查和静态检查)。
6、改错的最大忌 是“急躁 干”。人们常说“急中生智”,我不信,我认为大多数人着了急就会 干,早把“智”丢到脑后去了。不仅人如此,动物也如此。
7、调试的基本方法是“粗分细找”。对于隐藏得很深的Bug,我们应该运用归纳、推理、“二分”等方法先“快速、粗略”地确定错误根源的范围,然后再用调试工具仔细地跟踪此范围的源代码。如果没有调试工具,那么只好用“土办法”:在程序中插入打印语句,如printf(…),观看屏幕的输出。
8、现在主流的C++实现及其集成开发环境(IDE)大都提供了不止一个库,除了C++标准库(包括I/O和STL等)外,它们的开发商还提供了支持可视化事件驱动编程的类库,如MFC、OWL、VCL等,这几种库并不冲突,可以同时使用。此外还有一些第三方开发的程序库和类库,如果它们和其他库一起使用,就要考虑是否存在二进制兼容性问题。
9、尽量采用标准库中提供的函数和类来编程,而不要创建自制的版本。这不仅可以提高开发效率和程序的性能,而且可以改善程序的可移植性。因为这些库不仅是每一个语言实现必须提供的,而且它们经过精心的设计、调试和测试,可以保证高效而正确地执行。
10、MS C++/C应用程序的启动函数为mainCRTStartup()或者WinMainCRT- Startup(),同时在该函数的末尾调用了main()或者WinMain(),然后以它们的返回值为参数调用库函数exit(),因此也就默认了main()应该作为它的连接对象,如果找不到这样一个函数定义,自然会报错了。如此看来,main()其实就是一个回调函数。main()由我们来实现,但是不需要我们提供它的原型,因为我们并不能在自己的程序中调用它,这又和普通的回调函数有所不同。
11、C++标准对main()有几个不同于一般函数的限制:(1)不能重载。(2)不能内联。(3)不能定义为静态的。(4)不能取其地址。(5)不能由用户自己调用。
12、在C++中,重命名称为“Name-Mangling”(名字修饰或名字改编)。例如,在它们的前面分别添加所属各级作用域的名称(class、namespace等)及重载函数的经过编码的参数信息(参数类型和个数等)作为前缀或者后缀,产生全局名字Sample_1_foo@pch@1、Sample_1_foo@int@1、Sample_2_foo@pch@1和Sample_2_foo@int@1,这样就可以区分了
13、
14、一般来说,一个C++/C程序不可能不使用C运行时库,即使你没有显式地调用其中的函数也可能间接地调用,只是我们平时没有在意罢了。例如,启动函数、I/O系统函数、存储管理、RTTI、动态决议、动态链接库(DLL)等都会调用C运行时库中的函数。我们在每一个程序开头包含的stdio.h头文件中的许多I/O函数就是它的一部分。C运行时库有多线程版和单线程版,开发多线程应用程序时应该使用多线程版本的库,仅在开发单线程程序时才使用单线程版本。另外,同一软件的不同模块最好使用一致的运行时库,否则会出现连接问题。
15、内存单元访问的安全性和转换结果的安全性。主要表现为内存访问范围的扩张、内存的截断、尾数的截断、值的改变和溢出等。
16、
17、(1)避免使用前导“_”和“__”来定义你自己的标识符,因为语言及其实现使用它来定义一些内部名称或预定义的宏,因此如果你也使用它,就有可能造成命名冲突。(2)给标识符起一个有意义的名字,要能够“顾名思义”。如果是变量,最好能体现出它的值的类型(如使用类型名缩写作为前缀)。这样的标识符具有“自说明”能力,具体参见本书第11章。(3)使用长的标识符名字并不会增大可执行代码的体积,因此不要使用过于简单的名字,但也不要使用过长的名字。标识符名字的长度应该遵循“用最短的名字包含最多的信息量”的原则。
18、义序列是由反斜线()后跟一个特定转义字符组成的。其实由%引导的I/O格式控制字符序列,如%d、%f、%%等,也都是转义序列
19、三种基本控制结构只能有两种组合方式,那就是堆叠和嵌套
20、在你需要某种功能的函数时,首先应查看现有的库中是否提供了类似的函数。不要编写函数库中已有的函数,因为这不仅是重复劳动,而且自己编写的函数在各个质量属性方面一般都不如对应的库函数。库函数是经过严格测试和实践检验的。
21、我们在开发一些通用类的时候,应该设计并实现其完整的功能,而不需要去担心它的使用者会因为仅使用其中一小部分功能却要包含整个类定义而导致代码体积增大。
22、回调函数。这在事件驱动程序和多线程应用程序中很常见。
23、回调函数最典型的例子就是系统定时器回调函数和线程函数。首先为一个定时器注册一个回调函数,当定时器每次超时的时候,系统就会自动触发对这个回调函数的调用,在函数体内可以做你想做的事情。回调函数和普通的函数没有什么本质区别,也可以由用户自己显式地调用,只是当它作为回调函数的时候,其运行方式和普通函数有所不同。
24、同一个函数可以同时作为几个线程的函数。此时由于线程上下文切换,这个函数的多个执行流就可能出现重叠,而且每个执行流退出的时机不可预料,一个执行流的退出可能会破坏另一个执行流的堆栈。因此,线程函数并不使用普通的函数堆栈,而是使用线程自己的堆栈。线程堆栈是线程在每次启动时动态分配的,这样就可以在线程函数每次执行时使用不同的堆栈,从而避免线程函数执行流重叠时可能出现的堆栈破坏。此外,若一个函数可能会被多个线程调用的话,对于它们共享的数据要进行同步访问保护,并且避免使用static局部变量。
25、常使用的几个用来注册回调函数的系统函数有:set_new_handler()、atexit()、set_terminate()、beginthread()、set_unexpected()、signal()等。它们的具体用法可参考具体语言实现的帮助文档。



