读书笔记——《高质量C++/C编程指南》(2)

目录

前言

命名规则

共性规则

简单的Windows应用程序命名规则

表达式和基本语句

运算符优先级

复合表达式

if语句

布尔变量与零值比较

整型变量与零值比较

浮点变量与零值比较

指针变量与零值比较

对if 语句的补充说明

循环语句的效率

for 语句的循环控制变量

switch 语句

goto 语句


前言

读书笔记(1)对这本书里面的文件结构,以及代码风格做了记录,读书笔记(2)记录命名规则,表达式和基本语句的良好编程习惯。

命名规则

比较著名的命名规则有“匈牙利”法,——“在变量和函数名中加入前缀以增进人们对程序的理解”。

例如:

所有的字符变量均以ch 为前缀,若是指针变量则追加前缀p

如果一个变量由ppch 开头则表明它是指向字符指针的指针。


但是书中说:没有一种命名规则可以让所有的程序员赞同。即使这样也是给出了被大多数程序员采纳的命名规则。

共性规则

【规则1】标识符应当直观且可以拼读,可望文知意,不必进行“解码”。标识符最好采用英文单词或其组合,便于记忆和阅读。
【规则2】标识符的长度应当符合“min-length && max-information”原则。
例如:变量名maxval 就比maxValueUntilOverflow好用。单字符的名字也是有用的,常见的如i,j,k,m,n,x,y,z 等,它们通常可用作函数内的局部变量。
【规则3】命名规则尽量与所采用的操作系统或开发工具的风格保持一致。

例如:

Windows 应用程序的标识符通常采用“大小写”混排的方式,如AddChild。
而Unix 应用程序的标识符通常采用“小写加下划线”的方式,如add_child。

别把这两类风格混在一起用。

 【规则4】程序中不要出现仅靠大小写区分的相似的标识符。
【规则5】程序中不要出现标识符完全相同的局部变量和全局变量,尽管两者的作用域不同而不会发生语法错误,但会使人误解。
【规则6】变量的名字应当使用“名词”或者“形容词+名词”

例如:
float value;
float oldValue;
float newValue;


【规则7】全局函数的名字应当使用“动词”或者“动词+名词”(动宾词组)。
类的成员函数应当只使用“动词”,被省略掉的名词就是对象本身。

例如:
DrawBox(); // 全局函数
box->Draw(); // 类的成员函数

【规则8】用正确的反义词组命名具有互斥意义的变量或相反动作的函数等。

例如:
int minValue;
int maxValue;
int SetValue(…);
int GetValue(…);

【建议1】尽量避免名字中出现数字编号,如Value1,Value2 等,除非逻辑上的确需要编号。

简单的Windows应用程序命名规则


 【规则1】类名和函数名用大写字母开头的单词组合而成。


例如:
class Node; // 类名
class LeafNode; // 类名
void Draw(void); // 函数名
void SetValue(int value); // 函数名


【规则2】变量和参数用小写字母开头的单词组合而成。


例如:
BOOL flag;
int drawMode;


【规则3】常量全用大写的字母,用下划线分割单词

例如:
const int MAX = 100;
const int MAX_LENGTH = 100;
 

【规则4】静态变量加前缀s_(表示static)。


例如:
static int s_initValue; // 静态变量
 

【规则5】如果不得已需要全局变量,则使全局变量加前缀g_(表示global)。

例如:
int g_howManyPeople; // 全局变量
int g_howMuchMoney; // 全局变量

【规则6】类的数据成员加前缀m_(表示member),这样可以避免数据成员与成员函数的参数同名。
例如:

void Object::SetValue(int width, int height)
{m_width = width;m_height = height;
}



【规则7】为了防止某一软件库中的一些标识符和其它软件库中的冲突,可以为各种标识符加上能反映软件性质的前缀

例如:三维图形标准OpenGL 的所有库函数均以gl 开头,所有常量(或宏定义)均以GL 开头。

表达式和基本语句


表达式和语句都属于C++/C 的短语结构语法。它们看似简单,但使用时隐患比较多。

运算符优先级

C++/C 语言的运算符有数十个,运算符的优先级与结合律如下表所示。

注意一元运算符 + - * 的优先级高于对应的二元运算符

【规则1】如果代码行中的运算符比较多,用括号确定表达式的操作顺序,避免使用默认的优先级。为了防止产生歧义并提高可读性,应当用括号确定表达式的操作顺序

复合表达式

如 a = b = c = 0 这样的表达式称为复合表达式。

允许复合表达式存在的理由是:

(1)书写简洁;

(2)可以提高编译效率。但要防止滥用复合表达式。


【规则1】不要编写太复杂的复合表达式。
例如:i = a >= b && c < d && c + f <= g + h ; // 复合表达式过于复杂
【规则2】不要有多用途的复合表达式。

例如:d = (a = b + c) + r ;
该表达式既求a 值又求d 值。应该拆分为两个独立的语句:
a = b + c;
d = a + r;

【规则3】不要把程序中的复合表达式与“真正的数学表达式”混淆

例如:
if (a < b < c)

a < b < c 是数学表达式而不是程序表达式
并不表示if ((a<b) && (b<c))
而是成了令人费解的if ( (a<b)<c )

if语句


布尔变量与零值比较

【规则1】不可将布尔变量直接与TRUE、FALSE 或者1、0 进行比较

根据布尔类型的语义:

零值为“假”(记为FALSE)

任何非零值都是“真”(记为TRUE)。

TRUE 的值究竟是什么并没有统一的标准。

例如:Visual C++ 将TRUE 定义为1,而Visual Basic 则将TRUE 定义为-1。


假设布尔变量名字为flag

与零值比较的标准if 语句如下:
if (flag) // 表示flag 为真

if (!flag) // 表示flag 为假


与零值比较的不标准if 语句如下:
if (flag == TRUE)
if (flag == 1 )
if (flag == FALSE)
if (flag == 0)

整型变量与零值比较


【规则2】应当将整型变量用“==”或“!=”直接与0 比较
假设整型变量的名字为value,它与零值比较的标准if 语句如下:
if (value == 0)
if (value != 0)
不可模仿布尔变量的风格而写成
if (value) // 会让人误解 value 是布尔变量
if (!value)

浮点变量与零值比较

【规则3】不可将浮点变量用“==”或“!=”与任何数字比较
无论是float 还是double 类型的变量,都有精度限制。所以一定要避免将浮点变量用“==”或“!=”与数字比较,应该设法转化成“>=”或“<=”形式。

假设浮点变量的名字为x,
if (x == 0.0) // 隐含错误的比较
转化为
if ((x>=-EPSINON) && (x<=EPSINON))
其中EPSINON 是允许的误差(即精度)。

指针变量与零值比较


【规则4】应当将指针变量用“==”或“!=”与NULL 比较
指针变量的零值是“空”(记为NULL)。尽管NULL 的值与0 相同,但是两者意义不同。

假设指针变量的名字为p,它

与零值比较的标准if 语句如下:
if (p == NULL) // p 与NULL 显式比较,强调p 是指针变量
if (p != NULL)

与零值比较的不标准if 语句如下:
if (p == 0) // 容易让人误解p 是整型变量
if (p != 0)

if (p) // 容易让人误解p 是布尔变量
if (!p)

对if 语句的补充说明


有时候我们可能会看到 if (NULL == p) 这样古怪的格式。不是程序写错了,是程序员为了防止将 if (p == NULL) 误写成 if (p = NULL),而有意把p 和NULL 颠倒。编译器认为 if (p = NULL) 是合法的,但是会指出 if (NULL = p)是错误的,因为NULL不能被赋值。

程序中有时会遇到if/else/return 的组合,应该将如下不良风格的程序 

if (condition)return x;
return y;//改写为
if (condition)
{return x;
}
else
{return y;
}//或者改写成更加简练的
return (condition ? x : y);

循环语句的效率

C++/C 循环语句中,for 语句使用频率最高,while 语句其次,do 语句很少用。提高循环体效率的基本办法是降低循环体的复杂性。

【建议1】在多重循环中,如果有可能,应当将最长的循环放在最内层最短的循环放在最外层,以减少CPU 跨切循环层的次数。

【建议2】如果循环体内存在逻辑判断,并且循环次数很大,宜将逻辑判断移到循环体的外面

for (i=0; i<N; i++)
{if (condition)DoSomething();elseDoOtherthing();
}
if (condition)
{for (i=0; i<N; i++)DoSomething();
}
else
{for (i=0; i<N; i++)DoOtherthing();
}

 前者程序比后者程序多执行了N-1 次逻辑判断。

并且由于前者老要进行逻辑判断,打断了循环“流水线”作业,使得编译器不能对循环进行优化处理,降低了效率。

如果N 非常大,最好采用后者的写法,可以提高效率。

如果N 非常小,两者效率差别并不明显,采用前者的写法比较好,因为程序更加简洁。

for 语句的循环控制变量

【规则1】不可在for 循环体内修改循环变量,防止for 循环失去控制。
【建议1】建议for 语句的循环控制变量的取值采用“半开半闭区间”写法。

A:x 值属于半开半闭区间“0 =< x < N”,起点到终点的间隔为N,循环次数为N。
B:x 值属于闭区间“0 =< x <= N-1”,起点到终点的间隔为N-1,循环次数为N。
相比之下,写法A更加直观,尽管两者的功能是相同的。

switch 语句

有了 if 语句为什么还要switch 语句?在出现多分支选择的时候,switch比if更简介明了。

//switch 语句的基本格式是:
switch (variable)
{case value1 :// ⋯break;case value2 :// ⋯break;// ⋯default : //⋯break;
}

【规则1】每个case 语句的结尾不要忘了加break,否则将导致多个分支重叠
(除非有意使多个分支重叠)。
【规则2】即使程序不需要default 处理,也应该保留语句 default : break

goto 语句

由于goto 语句可以灵活跳转,如果不加限制,它的确会破坏结构化设计风格。其次,goto 语句经常带来错误或隐患。它可能跳过了某些对象的构造、变量的初始化、重要的计算等语句,

goto state;
String s1, s2; // 被goto 跳过
int sum = 0; // 被goto 跳过
//⋯
state:
//⋯


如果编译器不能发觉此类错误,每用一次goto 语句都可能留下隐患。
错误是程序员自己造成的,不是goto 的过错。goto 语句它能从多重循环体中一下跳到外面,用不着写很多次的break 语句;

{// ⋯{// ⋯{ //⋯goto error;}}
}error:
//⋯

所以我们主张少用、慎用goto 语句,而不是禁用。
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/8412.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自动驾驶中常见坐标系极其转换

各个传感器坐标系 相机坐标系统 摄像头的作用是把三维世界中的形状、颜色信息,压缩到一张二维图像上。基于摄像头的感知算法则是从二维图像中提取并还原三维世界中的元素和信息,如车道线,车辆、行人等,并计算他们与自己的相对位置。 感知算法和相机相关的坐标系有图像坐…

Pandas进阶

文章目录 第1关&#xff1a;Pandas 分组聚合第2关&#xff1a;Pandas 创建透视表和交叉表 第1关&#xff1a;Pandas 分组聚合 编程要求 使用 Pandas 中的 read_csv() 函数读取 step1/drinks.csv 中的数据&#xff0c;数据的列名如下表所示&#xff0c;请根据 continent 分组并…

MySQL-ELK基础

1&#xff1a;什么是 ELK ELK是由一家elastic公司开发的三个开源项目的首字母缩写&#xff0c;这三个项目分别是&#xff1a;Elasticsearch、Logstash 和 Kibana。三个项目各有不同的功能&#xff0c;之后又增加了许多新项目, 于是 从5.X版本后改名为Elastic Stack Elastic S…

【JavaScript】内置对象 - Date 日期对象 ④ ( 制作倒计时页面 )

文章目录 一、倒计时页面实现1、需求分析2、计算秒数3、计算倒计时时间的 天 / 时 / 分 / 秒4、页面中显示倒计时时间 二、完整代码示例1、完整代码2、执行结果 Date 日期对象参考文档 : https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Da…

速卖通商品评论API(aliexpress.item_review)返回值全解析

在电商领域&#xff0c;用户评论对于产品的推广和销售具有极其重要的影响。速卖通&#xff08;AliExpress&#xff09;作为全球知名的跨境电商平台&#xff0c;提供了丰富的API接口供开发者使用&#xff0c;其中aliexpress.item_review API允许开发者获取商品的评论信息。本文将…

品质为王:高效溶解性鱼油胶囊的软胶囊弹性硬度测试解析

品质为王&#xff1a;高效溶解性鱼油胶囊的软胶囊弹性硬度测试解析 在当今的健康产品市场中&#xff0c;高效溶解性鱼油胶囊以其独特的营养价值和吸收效率赢得了众多消费者的青睐。然而&#xff0c;要想在激烈的市场竞争中脱颖而出&#xff0c;产品的品质保证至关重要。其中&a…

深入理解WPF的ResourceDictionary

深入理解WPF的ResourceDictionary 介绍 在WPF中&#xff0c;ResourceDictionary用于集中管理和共享资源&#xff08;如样式、模板、颜色等&#xff09;&#xff0c;从而实现资源的重用和统一管理。本文详细介绍了ResourceDictionary的定义、使用和合并方法。 定义和用法 Res…

鸿蒙内核源码分析(信号消费篇) | 谁让CPU连续四次换栈运行

本篇有相当的难度&#xff0c;涉及用户栈和内核栈的两轮切换&#xff0c;CPU四次换栈&#xff0c;寄存器改值&#xff0c;将围绕下图来说明. 解读 为本篇理解方便&#xff0c;把图做简化标签说明: user:用户空间kernel:内核空间source(…):源函数sighandle(…):信号处理函数&a…

【操作系统】进程与线程概念基础知识

进程与线程概念基础知识 进程进程的概念进程控制块进程状态进程三状态模型挂起进程模模型进程的上下文切换进程控制 线程为什么引入线程线程的概念线程与进程的比较线程的上下文切换线程的实现 进程 进程的概念 1. 进程的定义&#xff1a; 进程是指一个具有一定独立功能的程序…

【面试干货】http请求报文的组成与作用?

【面试干货】http请求报文的组成与作用&#xff1f; 一、http 的请求报文组成二、请求行&#xff08;Request Line&#xff09;三、请求头部&#xff08;Request Headers&#xff09;四、请求体&#xff08;Request Body&#xff09;五、响应头部 &#xff08;Response Headers…

iframe的基本用法

一、背景 在web页面开发中,有时会遇到在一个应用A的页面中引用应用B的页面,此时就需要在应用A中使用iframe嵌入引用B的页面了,比如多租户的web应用,或者门户系统的智能客服助手弹框应用,博主也是在做通用智能客服应用的过程中用到了iframe。网络上有关iframe的信息虽然很…

银河麒麟桌面版开机后网络无法自动链接 麒麟系统开机没有连接ens33

1.每次虚拟机开机启动麒麟操作系统&#xff0c;都要输入账号&#xff0c;密码。 进入点击这个ens33 内网才连接 2. 如何开机就脸上呢&#xff1f; 2.1. 进入 cd /etc/sysconfig/network-scripts 2.2 修改参数 onbootyes 改为yes 2.3 重启即可 a. 直接重启机器查看是否正常&…

工程伦理课堂记录

文章目录 0. 导论0.1 工程伦理教育的意义0.2 工程伦理教育要实现的目标 1. 工程与伦理1.1 工程伦理学科的产生1.2 工程和技术1.3 工程概念的理解演进1.4 工程的过程1.5 工程的特点1.6 工程活动的七个维度总结 2. 伦理2.1 道德伦理的概念2.2 道德伦理的关系2.3 伦理规范2.4 伦理…

【吃透Java手写】2-Spring(下)-AOP-事务及传播原理

【吃透Java手写】Spring&#xff08;下&#xff09;AOP-事务及传播原理 6 AOP模拟实现6.1 AOP工作流程6.2 定义dao接口与实现类6.3 初始化后逻辑6.4 原生Spring的方法6.4.1 实现类6.4.2 定义通知类&#xff0c;定义切入点表达式、配置切面6.4.3 在配置类中进行Spring注解包扫描…

Blender动画与云渲染:创造高质量作品的未来路径

Blender作为开源的3D图形软件&#xff0c;在多个领域广受欢迎。但随着项目复杂度提升&#xff0c;传统渲染方式受限。云渲染技术的兴起突破了这些限制&#xff0c;为创作者提供了更自由、高效的创作环境。 一、Blender动画项目的挑战 传统上&#xff0c;Blender动画渲染需要依…

代码审计-php篇之某CRM系统多处sql注入

&#x1f31f; ❤️ 作者&#xff1a;yueji0j1anke 首发于公号&#xff1a;剑客古月的安全屋 字数&#xff1a;3516 阅读时间: 35min 声明&#xff1a;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果…

实战 | 实时手部关键点检测跟踪(附完整源码+代码详解)

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

苹果平板HOME键成历史,全面屏时代到来?2024平板电脑市场趋势分析

近期苹果公司在“放飞吧”发布会上推出了新款iPad Pro和iPad Air平板电脑&#xff0c;并下架了最后一款带有实体Home按键的iPad 9。这一变化标志着Home键在苹果iPad产品线中成为了历史&#xff0c;引起了不少网友的怀念和感慨。 与此同时&#xff0c;今年3月线上平板电脑市场迎…

【驱动】I2C读写时序

1、I2C总线 I2C使用两条线在主控制器和从机之间通信,SCL(串行时钟线)和SDA(串行数据线),这两条线需接5~10欧上拉电阻,总线空闲空闲时,SCL和SDA处于高电平,I2C总线标准模式速度可以达到100K/S,快速模式可以达到400K/S。 2、状态 I2C总线有四种状态:空闲、启动、忙碌、…

Unity与C#的关系

第一&#xff0c;我们首先需要知道Unity与C#的关系是什么&#xff1f; 第二&#xff0c;我们要明白为什么Unity会使用C#&#xff0c;而不是C&#xff1f; 第三&#xff0c;我们需要知道Unity是怎么使用C#的&#xff1f; 第一点&#xff1a; 先说结论&#xff1a;C#是Unity用…