C++基本语言特征
文章平均质量分 80
此专栏是2014年已出版著作《编码的法则:C++程序员不可不知的101条实用经验》第一篇连载,《编码的法则》第一篇为C++基本语言特征,介绍与C++基本语言特征相关的实用经验,希望此篇介绍的经验对你有用。
@一鸣惊人
这个作者很懒,什么都没留下…
展开
-
实用经验 60 关于#和##的讨论
对于#和##,我想一般的编程人员应该是比较陌生。因为编程时,我们用的比较少,其在程序库开发中使用较多。如MFC库的_T()宏,嵌入式底层封装库中使用也较多,在编程过程中,你可以合理的使用#和##,这样可以给我们的编程带来好处, 同样需注意#和##使用的陷阱。原创 2021-08-04 12:09:09 · 107 阅读 · 0 评论 -
实用经验 59 assert的副作用
读者应该都听说过assert断言。断言语句指定在程序的某些特定点应为真的条件。如果该条件不为真,则断言失败,中断程序的执行,在windows下会显示“断言失败”对话框,而linux会退出程序执行。assert宏在位于注释和异常之间的某个位置扮演了代码文档化及捕捉非法行为的适当角色。 assert最大问题在于它是一个伪函数,因此它也(无可避免地)带着伪函数的种种先天不足。原创 2021-08-03 23:32:11 · 543 阅读 · 0 评论 -
实用经验 58 防止重复包含头文件
头文件重复包含,是每个程序员都遇到过的问题。建议在每个头文件时采用“头文件卫士”加以保护。头文件卫士有两种形式一种是#progma once,一种是#ifndef。如果你的程序需要跨平台,建议你使用#ifndef方式。因为这种方式仅与C++语言有关。原创 2021-08-02 22:57:37 · 816 阅读 · 0 评论 -
实用经验 57 #define的使用陷阱
宏的强大作用在于在编译期自动地为我们产生代码。如果说模板可以通过类型替换来为我们产生类型层面上的多态,那么宏就可以通过符号替换在符号层面上产生的多态。正确合理地使用宏,可以有效地提高代码的可读性,减少代码的维护成本。原创 2021-08-01 23:36:43 · 549 阅读 · 0 评论 -
使用经验 56 使用#define定义字面值和伪函数
在编程时,为程序员提供一定方便,并能在一定程度上提高程序的执行效率。#define将一个标示符定义为一个字符串,该标示符被称为宏,被定义的字符串称为替换文本。宏定义不是C++的语句。在编译时使用宏的地方会发生字符串替换。在应用时,如果你定义一个字面值常量建议使用const替换#define。 宏定义不受名字空间的限制。在名字空间外依然可见。原创 2021-07-31 23:10:49 · 393 阅读 · 0 评论 -
第八章 预处理
预处理是C++程序编译的第一个步骤,预处理主要在源代码编译之前进行一些文本性质的操作。具体包括注释删除,插入被#include包含的文件内容、定义和替换有#define指令定义的符号,以及确定代码部分内容是否应根据一些条件编译指令进行编译。本章主要向读者展示C++编译器预处理所进行的不为知的事情、以及其存在的陷阱。通过本章学习,可让读者理解编译预处理。原创 2021-07-31 22:29:10 · 78 阅读 · 0 评论 -
实用经验 55 正确的使用字符串处理函数
在进行字符串操作时,请打起12分精神。因为无论你采用安全的字符串处理函数,还是普通的字符串处理函数。风险基本上是一样的。 字符串操作时,如果存在程序执行错误和程序异常时,优先保障系统正常运行,即使执行的结果是错误的。降低代价。原创 2021-07-30 21:56:32 · 172 阅读 · 0 评论 -
实用经验 54 请务必小心使用memcpy()系列函数
在C语言中,无论是内置数据类型、还是自定义数据类型都是POD对象。对于POD对象其内存模型都是可知的、透明的。针对POD对象,其二进制内容是可以随便复制的,在任何地方,只要其二进制内容在,就能还原出正确无误的POD对象。C++中的对象可能是POD的也可能是非POD的。因此在C++中使用memset和memcpy等函数要足够小心。原创 2021-07-29 21:11:51 · 962 阅读 · 1 评论 -
实用经验 53 请牢记字符串结束标志为’\0’
在C语言中,并没有字符串这种数据类型,其通过使用字符数组来保存字符串。通常所说的字符地址其实仅仅指其首地址,而字符串真正占用多大内存,这些完全依靠null结束符确定。在实际编程中C++的string字符串数据类具有C字符串所具有的所有功能,同时具有易于使用的优点。在字符串操作过程中,建议使用string替换c字符串原创 2021-07-28 22:01:35 · 3436 阅读 · 0 评论 -
实用经验 52 关于字符编码的讨论
字符编码其实就是一种映射规则。由于计算机只能理解二进制,我们在屏幕上看到的英文、汉字等字符都是二进制转换后的结果。按照何种约定将字符存储在计算机中,如‘a’用什么表示,称之为“编码”;反之,如何将存储在计算机中的二进制数值解析显示出来,称之为“解码”。理解字符和字符编码的机制是编写出优秀应用程序的前提。在Windows下无论你是否打算使用Unicode,都尽量将程序转换成支持Unicode的形式。Windows系统底层全部采用Unicode编码,而Linux则采用UTF-8编码。原创 2021-07-27 20:19:44 · 215 阅读 · 0 评论 -
第7章 字符和字符串
字符和字符串我们最常见不过了。几乎每个应用程序都会用到字符串,同样也会用到字符。因为字符串由字符组成。在C++中,字符串由一系列的字符组成,最后用一个特殊的字符’\0’标示字符串结束。由于字符串在内存中以二进制数据存储,字符串占用多大存储空间,一个字符占用几个字节,这些都是编程中最容易出问题的地方。当然这其中还涉及字符的编码问题。这些都是本章讨论的重点。最后,本章将从字符编码开始字符和字符串的讲解旅程,希望后续介绍的字符串陷阱能对你有所帮助。原创 2021-07-27 20:09:35 · 78 阅读 · 0 评论 -
实用经验 51 为何降低函数的圈复杂度?
降低函数的复杂度是提供软件质量的一个重要手段。一般情况下有9种技术可直接降低函数的圈复杂度。他们是提炼函数,替换算法,分节条件表达式,合并条件式,合并重复的条件片段,移除控制标记,将查询函数和修改函数分离,令函数携带参数,已明确函数取代参数。在降低函数圈复杂度的所有方法中,我们推荐依靠类函数重载多态机制降低函数圈复杂度的方法。原创 2021-07-25 22:57:16 · 619 阅读 · 0 评论 -
实用经验 50 尽量拒绝使用变参函数
变参函数具有很多的优点,为程序带来了很多的方便。但同时也存在很大的隐患。对于可变参函数,由于编译器对函数原型检查不够严格,所以很容易产生问题,并且很难发现;同时也不利于写成优秀的代码。实际中应尽量避免可变参函数。原创 2021-07-25 16:48:05 · 132 阅读 · 0 评论 -
实用经验 49 不要让main返回void
同C程序一样,每个C++程序都包含一个或多个函数,且必须有一个函数其名称为main,而且每个函数都要一定功能的语句序列组成。程序执行时,操作系统通过程序入口main函数,调用main函数开始程序的运行,程序执行完毕后返回一个值给操作系统。在大多数系统中,main函数的返回值说明程序的退出状态。如果main函数返回0,则代表main函数成功执行完毕,程序正常退出,否则代表程序异常退出。某些编译器main函数返回void或其他类型,这是不符合C++标准的。即使可以通过编译,也存在很多问题:如可移植性问题。原创 2021-07-24 23:11:21 · 1478 阅读 · 9 评论 -
实用经验 48 函数重载需考虑什么?
函数重载是指在同一作用域内,可以有一组具有相同函数名,不同参数列表的函数,这组函数被称为重载函数。重载函数通常用来命名一组功能相似的函数,这样做减少了函数名的数量,避免了名字空间的污染,对于程序的可读性有很大的好处。合理利用重载函数会给程序可读性带来好处,但不合理的重载函数不但对代码可读性没有帮助,还会污染名字空间。原创 2021-07-23 19:45:33 · 249 阅读 · 0 评论 -
实用经验 47 内联函数会像宏一样替换吗?
内联函数是C++语言新引入的概念。其目的是为了提高函数的执行效率。宏是C++从它的前辈C继承而来的,宏同样可以提高代码的执行效率,减少函数执行过程中的调用开销。不是所有函数都适合声明为内联函数。即使声明为内联函数也不一定编译器最终就会对此函数进行inline。只有那些代码行数1-5行,不包含循环,递归的函数才有可能最终inline。原创 2021-07-21 22:22:00 · 388 阅读 · 0 评论 -
实用经验 46 函数传值、传指针及传引用的效率分析
C++规定函数参数传递有三种:传参数的值(称值传递,简称传值),传参数的地址(称地址传递,简称传指针) ,传参数的引用(称引用传递,简称传引用)。三种函数调用方式,各有各的好处,一般引用和指针效率相仿。传值调用效率依使用环境而定;对内建的数据类型优先使用值传递,而对于自定义的数据类型,特别是传递较大的对象,那么优先使用引用传递。原创 2021-07-20 22:40:08 · 1776 阅读 · 5 评论 -
实用经验 45 禁止函数返回局部变量的引用
局部变量和引用是每个C++程序员都不会陌生的两个概念。是使用最多同时也是出问题最多的两个概念。引用是被绑定变量或对象的别名。局部变量,顾名思义就是在局部范围内有效的变量。在实际应用中,保证返回数据超出函数范围后依然有效。像返回局部变量的引入就是不靠谱的事情。返回new生成的对象,同样不是一个可取的方法。因为这样的代码层次混乱,会让代码上层使用人员苦不堪言。原创 2021-07-19 20:56:12 · 372 阅读 · 0 评论 -
第6章 函数
函数是C++语言中最重要的部分之一,地位等同于数组、内置类型。可以这么说:没有函数C++语言程序将无法运行,因为每个程序都要一个入口main主函数。通过函数,相同功能的代码段可独立到一个地方,提高代码的可重用性,降低代码的耦合性,增强程序的安全性。如何设计和实现函数,不仅关系到代码的正确性,同时还关系到代码的执行效率。函数是使用最多的C++语言特征,同时亦是陷阱最多的地方。本章的议题也许可以帮助你避开这些陷阱。原创 2021-07-18 10:13:59 · 62 阅读 · 0 评论 -
实用经验 44 关于循环语句的讨论
循环语句是C++中最重要的逻辑控制语句,C++提供for语句,while语句,do语句三种循环控制语句。其中for语句的使用频率最高,while语句其次,do语句主要在一些特殊的场合使用,使用频率较小。使用do…while实现的宏定义可提高代码的健壮性。在循环时,为了提高循环的效率。应将循环次数小的循环放到外层。循环次数大的放到内层。原创 2021-07-18 09:31:56 · 220 阅读 · 2 评论 -
实用经验 43 同魔鬼数字说再见
魔鬼数字,也被称为幻数。指的是那些上下文里出现的字面常量。魔鬼数字可以是数字,也可以使字符串。魔鬼数字最主要的问题不是他影响程序的功能,而是他没有抽象语义,影响程序的可读性。当我们阅读和维护程序时,我们不得不一个个地搞清楚每个光秃秃的数字到底代表了什么意思。没错,通过这种方式我们确实也可以勉强度日。但是为了读懂代码,我们付出了很多的精力。但是有时我们理解的可能还不是很准确。原创 2021-07-17 09:40:29 · 654 阅读 · 0 评论 -
实用经验 42 条件操作符和逗号操作符
逗号操作符和条件操作符是C++中两个特殊的操作符。他们有着其固有的求值顺序和使用环境。条件操作符可以给我的代码带来简化,逗号操作符中的每个表达式会被求值,而整个表达式的值却是最后一个表达式的值。原创 2021-07-16 19:22:52 · 173 阅读 · 0 评论 -
实用经验 41 goto真的一无是处吗?
goto语句把程序的执行流从一条语句转移到令一条语句,在一般情况下,我们应该避免使用。在某些环境下,例如错误处理以及释放资源,跳出多层循环,使用goto语句往往可给我们带来程序简洁。提高可读性的优点原创 2021-07-15 21:06:36 · 1060 阅读 · 2 评论 -
实用经验 40 标示语句结束的分号的思考
分号标示c++语句结束,多了一个分号;、少了一个分号;都可能造成不良的后果。程序员在程序编写过程中应该小心谨慎,不让这种错误成为你程序编写和编译的绊脚石。原创 2021-07-14 21:46:31 · 192 阅读 · 2 评论 -
实用经验 39 “悬挂”else引起的问题
“悬挂”else问题,应该是我们最熟悉不过的一个问题了。此问题也不是C/C++所独有。即使有多年软件开发经验的资深程序员也常常深受其害。解决这一问题最佳方案是让我们不屑的优秀的编码风格。也就是在if和else之后加上一对大括号,不论if-else之间有几条语句,也不论else后有几条语句。原创 2021-07-13 21:38:24 · 422 阅读 · 2 评论 -
实用经验 38 a || b和a&&b的陷阱
||和&&是C++中的逻辑或和逻辑与操作符。对于逻辑与操作符当且仅当a和b都为true,其结果才为true。对于逻辑或操作符当且仅当a和b都为false,其结果才为false。 逻辑与&&和逻辑或||都具有短路求值的特性,在使用时需注意了,如你使用正确会给你带来益处,如果你使用不当可能会给你带来致命的陷阱。明确区分逻辑或(与)和位或(与)的差异。原创 2021-07-12 22:31:37 · 1072 阅读 · 2 评论 -
实用经验 37 switch-case的陷阱
Switch-case语句主要用在多分支条件的环境中,在这种环境中使用if语句会存在繁琐而且效率不高的弊端。在使用switch-case结构时,在每个case标号分支语句最后,请务必添加一个break。如果在某些特殊情况下break不在需要了。建议你在此处添加注释进行说明。除default标号外,每个case标号必须是一个常量表达式。且不能存在两个case标号相同的情形。原创 2021-07-11 20:13:02 · 597 阅读 · 1 评论 -
实用经验 36 表达式求值顺序不要想当然
表达式计算顺序是一个很繁琐,但是很必要的话题。在函数实参调用时,时刻注意你的调用形式是否存在求值顺序的问题。让你的函数不要依赖计算顺序。针对操作符优先级,建议你多写几个括号,这样可以把你的意图表达的更清晰。但对于操作数的求值顺序问题,你的这样做法。对操作数的求值顺序无任何影响。在这种情况下,建议你使用显示的、手工指定中间变量的手段解决。原创 2021-07-10 21:39:25 · 380 阅读 · 1 评论 -
实用经验 35 尽量使用C++转换操作符
有C++编程经验的人,都会有这样的一个常识:除非必要,尽量不要对变量进行强制转换。这是因为强制转换是存在风险的。然而实际上有些事情有点儿事与愿违。也就是说在某些情况下,转型是必须的。由于强制类型转换无所不能,会给C++程序带来很大的安全隐患。因此建议在C++代码中使用C++提供的除reinterpret_cast以外的3种转换方式。除非必要禁止使用强制类型转换和reinterpret_cast。原创 2021-07-09 22:15:19 · 187 阅读 · 6 评论 -
实用经验 34 运算符引发的混乱
C++和它的前辈C确实紧密相连,C++从C那儿继承了很多的东西。其中也包括一套含义模糊不清的运算符。也正是由于这套运算符,加之C++那套灵活的语法,才导致了很多程序员C++运算符的使用混乱。按照产生混乱的原因,C++运算符的混乱可分为:粗心导致的混乱,优先级带来的换乱,结合性带来的混乱。原创 2021-07-08 21:42:11 · 173 阅读 · 1 评论 -
第5章 表达式和语句
语句类似于自然语言中的句子,语句是C++程序的重要组成部分。可以这么说没有语句也就没程序的存在了。语句由包含了各种各样的表达式,如算术表达式,逻辑表达式。本章的讨论对象就是表达式和语句。本章的议题着重探讨C++表达式和语句使用中容易被你忽视的陷阱。希望通过本章的讨论,您可对C++语言中的语句和表达式有一个更为深刻的认识。掌握语句和表达式使用中不为人知的秘密和陷阱。原创 2021-07-08 21:28:24 · 106 阅读 · 0 评论 -
实用经验 33 引用和指针的差异
从编程的角度考虑,指针和引用并没有太大的区别。但在有些情况下如果采用引用替代指针,可带来代码简洁清晰,易于理解的效果。 请记住并非所有适合指针的地方,引用都能替换。原创 2021-07-07 11:44:15 · 297 阅读 · 1 评论 -
实用经验 32 多维数组和指针
多维数组是对一维数组的扩展,如果1维数组的元素也是1维数组,便构成了2维数组。以此类比如果2维数组的元素类型是一维数组,那便构成3维数组了。多维数组名和多重指针在任何时候都不等价。在C++中多维数组就是一维数组,只是数组中的每个元素又是一个数组。多重指针指的是指向另一个指针的指针。原创 2021-07-06 22:41:50 · 310 阅读 · 1 评论 -
实用经验 31 臭名昭著空指针到底是什么?
空指针必须是指向不能被变量分配到的地址; 程序员请求一个空指针时,无论写“0“还是“NULL”,都是有编译器来生成适合机器的空指针的二进制表达形式;利用空指针(NULL)而非0,提高程序运行效率原创 2021-07-05 08:04:30 · 1028 阅读 · 3 评论 -
实用经验 30 防微杜渐,拒绝野指针
野指针,又名迷途指针。即指向“垃圾”内存的指针。此时指针所指向的内存已被操作系统回收。可执行程序已经无法在访问了。由于指针引起的编程错误大部分是野指针造成的。但是指针不不知晓此段内存已释放。这是产生野指针的主要原因。合理的使用引用和智能指针加上优秀的编程规范和在一定程度上降低野指针原创 2021-07-04 08:07:34 · 212 阅读 · 3 评论 -
实用经验 29 禁止以多态的形式处理数组
继承和多态是C++面向对象的重要概念。采用继承和多态,你可通过指向基类对象指针和引用,来操作子类对象的函数。继承是C++实现面向对象的基础。同样C++也允许你通过指针或引用来操作子类元素形式的数组。但即使C++允许这种应用方式,你也不要沾沾自喜。因为在某些环境下,其表现也许会让你失望。 禁止以多态的形式处理数组,以防产生不可以预知的运行错误。原创 2021-07-03 08:33:19 · 95 阅读 · 0 评论 -
实用经验 28 充满疑惑的数组指针和指针数组
明确辨别指针数组和数组指针。不要将其混为一谈,指针数组表示声明的变量是一个数组,数组中的元素为指针。而数组指针则表示声明的变量为一个指针,此指针指向一个数组。原创 2021-06-30 21:06:59 · 135 阅读 · 0 评论 -
实用经验 27 再论数组和指针的差异性
不要把数组混为一谈,否则你会为之付出惨痛代价。数组标示一块区域,数组名称不占用内存。指针指向一块区域,指针会分配内存。你可以把数组名称当做一个const指针。但它绝非const指针那么简单;使用数组定义变量,声明此数组供其他地方使用时。一定要保持声明和定义一致,不能把数组声明为指针。原创 2021-06-30 20:54:35 · 149 阅读 · 0 评论 -
实用经验 26 论数组和指针的等价性
在C/C++中,数组和指针的关系颇为特殊,有点儿像文学中诗和词的关系:诗和词都是文学形式之一,存有不少的相同之处,但是在表现手法上有各具春秋。两者有时可等同看待,有时不能等同看待。原创 2021-06-30 08:28:05 · 1275 阅读 · 0 评论 -
实用经验 25 理解指针的本质
指针指地址,指针变量指存放地址的变量。指针的类型并不是指针本身的类型,而是指指针所指对象的类型。使用const修饰指针,const出现的位置的不同,指针的属性也不同。如果const位于*左方,则说明指针指向的对象为const对象。如果const位于*的右方,则说明指针为const指针。 在32为系统下,指针变量的大小是4字节。无论此指针变量是什么类型。原创 2021-06-29 22:00:38 · 285 阅读 · 2 评论