读书笔记——《高质量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();
    else
        DoOtherthing();
}
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 语句,而不是禁用。
 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据库大作业——基于qt开发的图书管理系统(四)项目目录的整理与绘制登录页面

项目目录的管理 前言 在上几篇的文章里面我们完成了基本环境的搭建,整理了项目数据库表结构并且成功的手动的加载了Qt的mysql数据库驱动&#xff0c;现在就要开始完成项目准备工作的最后一步:构建项目目录,一个好的项目离不开一个好的代码组织结构,所以在开始动手写我们这个项…

Java | Leetcode Java题解之第70题爬楼梯

题目&#xff1a; 题解&#xff1a; public class Solution {public int climbStairs(int n) {double sqrt5 Math.sqrt(5);double fibn Math.pow((1 sqrt5) / 2, n 1) - Math.pow((1 - sqrt5) / 2, n 1);return (int) Math.round(fibn / sqrt5);} }

无人机+通信中继:短波电台技术详解

随着无线通信技术的不断发展&#xff0c;无人机作为一种新型的信息传输平台&#xff0c;已经在多个领域得到了广泛应用。其中&#xff0c;无人机与短波电台的结合&#xff0c;为通信中继领域带来了全新的可能性。本文将详细解析无人机在通信中继中的应用&#xff0c;以及短波电…

产品专访|“产品”远程运维系统与“设备”远程运维系统的区别?

在日益复杂的工业制造环境下&#xff0c;远程运维已经成为生产制造企业不可或缺的一部分。在这个大背景下&#xff0c;产品远程运维系统和设备远程运维系统的需求越来越多&#xff0c;各自发挥着独特的作用。然而&#xff0c;尽管它们都涉及到远程运维的概念&#xff0c;但在实…

Nest.js中使用任务调度

java中的xxl在nestJs中是有内置的任务调度nestjs/schedule npm install --save nestjs/schedule 在model中引入使用 在service中直接使用就行 具体间隔多久看官方配置 Task Scheduling | NestJS 中文文档 | NestJS 中文网

STM32F1#1(入门了解)

一、STM32开发平台和工具 1.1 STM32芯片介绍 典型微控制器由CPU&#xff08;运算器、控制器&#xff09;、RAM、ROM和输入输出组成。 1.2 STM32核心板 STM32核心板配件&#xff1a; ①JTAG/SWD仿真-下载器 ②通信-下载模块 ③OLED显示屏 1&#xff09; 通信-下载模…

智慧工厂管理系统

随着科技的飞速发展&#xff0c;传统工厂正经历着一场前所未有的变革。在这个以智能化、信息化为主导的新时代&#xff0c;HiWoo Cloud平台以其卓越的智慧工厂管理系统&#xff0c;成为了众多企业转型升级的首选工具。今天&#xff0c;就让我们一起走进HiWoo Cloud的世界&#…

FTTR(光猫)ITMS注册NCE纳管

ITMS注册 TR069交互过程&#xff1a; 1.1. TR069交互—主动连接机制 主动连接机制是指CPE主动发出请求连接事件(事件可以为&#xff1a; 0 BOOTSTRAP&#xff1b; 1 BOOT; PERIODIC等等)给ACS。在连接建立之后才能进行业务处理(通过调用RPC方法实现)。 备注&#xff1a;政企…

【2024最新华为OD-C卷试题汇总】字符串分割(100分) - 三语言AC题解(Python/Java/Cpp)

&#x1f36d; 大家好这里是清隆学长 &#xff0c;一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C卷的三语言AC题解 &#x1f4bb; ACM银牌&#x1f948;| 多次AK大厂笔试 &#xff5c; 编程一对一辅导 &#x1f44f; 感谢大家的订阅➕ 和 喜欢&#x1f497; 文章目录 前…

2024.5.8

聊天框完善 #include "mywidget.h" #include "ui_mywidget.h"MyWidget::MyWidget(QWidget *parent): QWidget(parent), ui(new Ui::MyWidget) {ui->setupUi(this);//设置窗口大小this->resize(400,560);//设置窗口图标和标题this->setWindowTit…

快过VS Code,10天暴增20k star,高性能多人协作IDE横空出世

道歉 其实不意味着道歉的人错了 而是他认为这段关系 比自己的尊严更重要 失败了 不是说你有多差 而是说 你需要更努力了 写代码最重要的一个选择就是选哪个IDE了&#xff0c;目前主流的选择是vscode和IDEA了。 但是vscode虽然轻量&#xff0c;但是对于大型的项目仍然显得…

C语言----杨辉三角

各位看官们好。学习到这里想必大家应该对C语言的了解也是很深刻的了吧。但是我们也不能忘记我们一起学习的知识啊。在我们以前学习C语言的时候我想大家应该都听说过杨辉三角吧。虽然我们把其中的规律找到那么这个代码就简单很多了。那么接下里我们就来讲讲杨辉三角。 首先我们先…

实战28套JAVA高端架构P6/P7/P8架构—全栈架构

概述 Java SE Java SE&#xff08;Java Platform&#xff0c;Standard Edition&#xff09;。Java SE 以前称为J2SE。它允许开发和部署在桌面、服务器、嵌入式环境和实时环境中使用的Java应用程序。Java SE 包含了支持Java Web 服务开发的类&#xff0c;并为Java Platform&…

Web服务器和Tomcat

Web介绍 对于http协议操作进行封装、简化web程序开发 部署web项目&#xff0c;对外提供上网信息浏览 Tomcat介绍 一个轻量级的web服务器 也称为web容器 Tomcat的文件夹介绍 下载地址&#xff1a;Apache Tomcat - Apache Tomcat 9 Software Downloads 安装&#xff1a;直…

「YashanDB迁移体验官」Oracle向YashanDB迁移的丝滑体验

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 作者&#xff1a;IT邦德 中国DBA联盟(ACDU)成员&#xff0c;10余年DBA工作经验&#xff0c; Oracle、PostgreSQL ACE CSDN博客专家及B站知名UP主&#xff0c;全网粉丝10万 擅长主流Oracle、My…

【数据可视化-01】Matplotlib图形实战宝典

在数据分析领域&#xff0c;图形化展示数据是非常重要的环节。Python中的matplotlib库是绘制各类图形的强大工具。本文将介绍如何使用matplotlib绘制折线图、直方图、饼图、散点图和柱状图等数据分析中常见的图形&#xff0c;并附上相应的代码示例&#xff0c;可以当初matplotl…

GD32F103RCT6/GD32F303RCT6(9)高级定时器互补PWM波输出实验

本文章基于兆易创新GD32 MCU所提供的2.2.4版本库函数开发 后续项目主要在下面该专栏中发布&#xff1a; 手把手教你嵌入式国产化_不及你的温柔的博客-CSDN博客 感兴趣的点个关注收藏一下吧! 电机驱动开发可以跳转&#xff1a; 手把手教你嵌入式国产化-实战项目-无刷电机驱动&am…

第 8 章 电机测速(自学二刷笔记)

重要参考&#xff1a; 课程链接:https://www.bilibili.com/video/BV1Ci4y1L7ZZ 讲义链接:Introduction Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程 8.3.3 电机测速01_理论 测速实现是调速实现的前提&#xff0c;本节主要介绍AB相增量式编码器测速原理。 1.概…

深度学习——前馈全连接神经网络

前馈全连接神经网络 1.导入需要的工具包2.数据导入与数据观察&#xff08;1&#xff09;读取csv的文件信息&#xff1a;&#xff08;2&#xff09;训练数据前5行&#xff08;3&#xff09;打印第一个图&#xff08;4&#xff09;观察数据中的信息&#xff08;5&#xff09;查看…

浏览器输入URL到页面展示的过程详解

重点面试题&#xff1a;当你的浏览器中地址栏输入地址并回车的一瞬间到页面能够展示回来&#xff0c;经历了什么&#xff1f; step 1、URL解析 URL&#xff1a;internet上的每一个网页都具有一个唯一的名称标识&#xff0c;通常称之为URL&#xff08;Uniform Resource Locator…