《C++高级编程》读书笔记(三:编码风格)

news2024/12/29 7:42:02

1、参考引用

  • C++高级编程(第4版,C++17标准)马克·葛瑞格尔

2、建议先看《21天学通C++》 这本书入门,笔记链接如下

  • 21天学通C++读书笔记(文章链接汇总)

1. 为代码编写文档

  • 在编程环境下,文档通常指源文件中的注释

1.1 使用注释的原因

1.1.1 说明用途的注释
  • 使用注释的原因之一是:说明客户如何与代码交互。通常而言,开发人员应当能够根据函数名、返回值的类型以及参数的类型和名称来推断函数的功能。但是,代码本身不能解释一切。有时,一个函数需要一些先置条件或后置条件,而这些需要在注释中解释。函数可能抛出的异常也应当在注释中解释
  • 示例:C++ 中无法说明数据库对象的 saveRecord() 方法只能在 openDatabase() 方法之后调用,否则将抛出异常
    /*
        Throws:
        DatabaseNotOpenedException if the openDatabase() method has not been called yet.
    */
    RecordID saveRecord(Records record); // RecordID 只是 int 的别名,但用途一目了然
    

注意:编写注释时,那些可通过函数名返回值类型以及形参的类型和名称明显看出的信息,就不必添加到注释中

1.1.2 用来说明复杂代码的注释
  • 对于专业领域中较为复杂的代码,较好的做法是使用注释描述所使用的算法,并说明(循环的)不变量。不变量是执行一段代码的过程中必须为真的条件,例如循环的迭代条件

在这里插入图片描述

1.1.3 传递元信息的注释
  • 使用注释的另一个原因是:在高于代码的层次提供信息。元信息提供创建代码的详细信息,但不涉及代码的特定行为。例如,某组织可能想使用元信息跟踪每个方法的原始作者。还可使用元信息引用外部文档或其他代码
  • 下例给出了元信息的几个实例,包括文件的作者、创建日期、提供的特性。此外还包括表示元数据的行内注释,例如对应某行代码的 bug 编号,提醒以后重新访问时代码中某个可能的问题

在这里插入图片描述

1.2 注释的风格

1.2.1 每行都加入注释
  • 避免缺少文档的方法之一是在每行都包含一条注释。每行都加入注释,可以保证已编写的所有内容都有特定的理由。但在实际中,如果代码非常多,过多的注释会非常混乱、繁杂,无法做到
  • 通常没必要给每行代码都添加注释,但当代码非常复杂,需要这样做时,不要只是将代码翻译成英语,而要解释代码实际上在做什么
    if (result % 2 == 0){} // 错误:如果 result 对 2 求模结果为 0 
    if (result % 2 == 0){} // 正确:如果 result 为偶数 
    
1.2.2 前置注释
  • 团队可能决定所有的源文件都以标准注释开头,可以在该位置记录程序和特定文件的重要信息。在每个文件顶部加入的说明信息有
    • 最近的修改日期
    • 原始作者
    • 前面所讲的修改日志文件
    • 给出的功能 ID
    • 版权信息
    • 文件或类的简要说明
    • 未完成的功能
    • 已知的 bug
1.2.3 固定格式的注释
  • 以标准格式编写可被外部文档生成器解析的注释是一种日益流行的编程方法。对于 C++ 而言,免费工具 Doxygen(www.doxygen.org) 可解析注释,自动生成HTML文档、类图、UNIX man 页面和其他有用文档
1.2.4 特殊注释
  • 在添加注释前,首先考虑能否通过修订代码来避免使用注释。例如,重命名变量、函数和类,重新排列代码步骤的顺序,引入完好命名的中间变量等
  • 如果处理不太明显的 API,应在解释 API 的地方包含对 API 文档的引用
  • 更新代码时记得更新注释。如果代码的文档中充斥着错误信息,会让人非常困惑
  • 如果使用注释将某个函数分为多节,考虑这个函数能否分解为多个更小的函数

2. 分解

  • 分解是指将代码分为小段,理想状态下,每个函数或方法都应该只完成一个任务
  • 任何非常复杂的子任务都应该分解为独立的函数或方法

2.1 通过重构分解

  • 重构(refactoring)指重新构建代码的结构,下面给出了一些可用来重构代码的技术
    • 增强抽象的技术
      • 封装字段:将字段设置为私有,使用获取器和设置器方法访问它们
      • 让类型通用:创建更通用的类型,以更好地共享代码
    • 分割代码以使其更合理的技术
      • 提取方法:将大方法的一部分转换成便于理解的新方法
      • 提取类:将现有类的部分代码转移到新类中
    • 增强代码名称和位置的技巧
      • 移动方法或字段:移到更合适的类或源文件中
      • 重命名方法或字段:改为更能体现其作用的名称
      • 上移(pullup):在 OOP 中,移到基类中
      • 下移(push down):在 OOP 中,移到派生类中

2.2 通过设计来分解

  • 如果使用模块分解,可将以后编写的部分代码放在模块、方法或函数中,程序通常不会像把全部功能放在一起的代码那样密集,结构也更合理
  • 当然,仍然建议在编写代码之前设计程序

3. 命名

  • 编译器有几个命名规则
    • 名称不能以数字开头(例如 9to5)
    • 包含两个下划线的名称(例如 my__name)是保留名称,不应当使用
    • 以下划线开头(例如 _Name)的名称是保留名称,不应当使用

3.1 选择恰当的名称

在这里插入图片描述

3.2 命名约定

  • 1. 计数器

    • 程序员习惯把 i 和 j 分别用作计数器和内部循环计数器,然而要小心嵌套循环时搞混
    • 使用二维数据时,与使用 i 和 j 相比,将 row 和 column 用作索引会更容易
  • 2. 前缀
    在这里插入图片描述

  • 3. 匈牙利表示法

    • 匈牙利表示法是关于变量和数据成员的命名约定,其基本思想是使用更详细的前缀而不是一个字母 (例如 m) 表示附加信息
  • 4. 获取器和设置器

    • 如果类包含了数据成员例如 mStatus,习惯上会通过获取器 getStatus() 和设置器 setStatus() 访问这个成员
    • 要访问布尔数据成员,通常将 is(而非 get) 用作前缀,例如 isRunning()
  • 5. 大写

    • 变量和数据成员几乎总以小写字母开头,并用下划线 (my_queue) 或大写字母 (myQueue) 分隔单词
    • 函数和方法通常将首字母大写,但是本书采用小写风格的函数和方法,把它们与类名区别开来
    • 大写字母可用于为类和数据成员名指明单词的边界

4. 使用具有风格的语言特性

4.1 使用常量

  • C++ 语言提供了常量,可以把一个符号名称赋予某个不变的值 (例如 2.71828)
    const double kApproximationForE = 2.71828182845904523536;
    

4.2 使用引用代替指针

  • 用引用替换指针有许多好处
    • 1、首先,引用比指针安全,因为引用不会直接处理内存地址,也不会是 nullptr
    • 2、其次,引用在文体上比指针好,因为引用使用与堆栈变量相同的语法,没有使用 * 和 & 等符号
    • 3、使用引用的另一个好处是它明确了内存的所有权
      • 如果一个程序员编写了一个方法,另一个程序员传递给它一个对象的引用,很明显可以读取并修改这个对象,但是无法轻易地释放对象的内存。如果传递的是一个指针,就不那么明显

    用指针传递未必意味着对象将改变,因为参数可能是 const T*。传递指针或引用是否会修改对象,都取决于函数原型是否使用了 const T*、T*、const T& 或 T&

5. 格式

5.1 关于大括号对齐的争论

  • 本书中,除了函数、类和方法名之外,大括号与起始语句放在同一行
void someFunction 
{
    if (condition) {
        cout << "condition was true" << endl;
    } else {
        cout << "condition was false" << endl;
    }
}

5.2 关于空格和圆括号的争论

  • 本书在任何关键字之后都会使用空格,在运算符前后都会使用空格,在参数列表或函数调用中的每个逗号之后都会使用空格,并使用圆括号表明操作顺序
if (i == 2) {
    j = i + (k / m);
}

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

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

相关文章

Android系统的Ashmem匿名共享内存子系统分析(5)- 实现共享的原理

声明 其实对于Android系统的Ashmem匿名共享内存系统早就有分析的想法&#xff0c;记得2019年6、7月份Mr.Deng离职期间约定一起对其进行研究的&#xff0c;但因为我个人问题没能实施这个计划&#xff0c;留下些许遗憾…文中参考了很多书籍及博客内容&#xff0c;可能涉及的比较…

springboot源码分析-jar启动

概述 Spring Boot 提供了 Maven 插件 spring-boot-maven-plugin&#xff0c;可以方便的将 Spring Boot 项目打成 jar 包或者 war 包。 SpringBoot 是如何通过jar包启动的 java -jar做了什么&#xff1f;看看官网怎么说 If the -jar option is specified, its argument is the …

基础算法(一)——补

快排 归并排序和快速排序的时间复杂度都是 O(nlogn) 左右两边设置哨兵&#xff0c;分成左边小于x, 右边大于x。 &#xff08;先分交换&#xff0c; 再递归&#xff09; #include<iostream> using namespace std; const int N1e610; int n; int q[N]; void quick_sort(i…

【计算机视觉】手把手教你配置stable-diffusion-webui进行AI绘图(保姆级教程)

文章目录 一、前言二、本地化部署的要求三、使用的项目Stable diffusion WebUI项目四、电脑环境配置4.1 安装Anaconda4.2 看版本4.3 配置库包下载环境&#xff0c;加快网络速度4.4 创建环境4.5 激活环境4.6 安装git4.7 安装cuda 五、Stable diffusion环境配置5.1 下载Stable di…

【博学谷学习记录】超强总结,用心分享丨人工智能 LLM langchain初步了解简记

目录 LangChain及必知概念LoadersDocumentText Spltters 文本分割Vectorstores 向量数据库Chain 链Agent 代理Embedding LangChain及必知概念 LangChain 是一个用于开发由语言模型驱动的应用程序的框架。他主要拥有 2 个能力&#xff1a; 可以将 LLM 模型与外部数据源进行连接…

009-从零搭建微服务-系统服务(二)

写在最前 如果这个项目让你有所收获&#xff0c;记得 Star 关注哦&#xff0c;这对我是非常不错的鼓励与支持。 源码地址&#xff08;后端&#xff09;&#xff1a;https://gitee.com/csps/mingyue 源码地址&#xff08;前端&#xff09;&#xff1a;https://gitee.com/csps…

Flowable开始事件-定时开始事件

文章目录 定时开始事件一、定义1. 图形标记2. XML标记2.1、在指定时间点执行2.2、指定定时器之前要等待多长时间&#xff0c; timeDuration可以设置为timerEventDefinition的子元素。2.3、指定重复执行的间隔&#xff0c; 可以用来定期启动流程实例&#xff0c;或为超时时间发送…

NLP的idea,看了就能水一篇论文

1.问题 在中文情感分析任务中,已有方法仅从单极、单尺度来考虑情感特征&#xff0c;无法充分挖掘和利用情感特征信息&#xff0c;模型性能不理想。 单级单尺度&#xff1a;只从一个方面学习文本的特征 多级多尺度&#xff1a;应该是分别从不同方面学习文本的特征&#xff0c…

电脑vcomp140.dll丢失怎么修复

vcomp140.dll是Microsoft的Visual C Redistributable for Visual Studio 2015的一部分。它是一个动态链接库文件&#xff0c;主要用于在Windows操作系统上运行使用Visual Studio 2015编写和编译的软件。与其他许多Windows动态链接库文件类似&#xff0c;vcomp140.dll包含函数和…

(二)CSharp-索引器

1、索引器定义 什么是索引器 索引器&#xff08;indexer&#xff09;是这样一种成员&#xff1a;它使对象能够用与数组相同的方式&#xff08;即使用下标&#xff09;进行索引 索引器的声明参见 C# 语言定义文档注意&#xff1a;没有静态索引器 索引器是一组 get 和 set 访问…

案例32:基于Springboot在线远程考试系统开题报告设计

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

地震勘探基础(十一)之水平叠加处理

水平叠加处理 地震资料经过预处理&#xff0c;静校正&#xff0c;反褶积&#xff0c;速度分析和动校正处理后就要进行水平叠加处理。地震水平叠加处理是地震常规处理的重要环节。 假设一个共中心点道集有三个地震道&#xff0c;经过速度分析和动校正以后&#xff0c;水平叠加…

【PCIE】TLP 发送三阶段和Secondary Bus Reset

TLP传输三阶段 TLP 发送的三个阶段涉及到 PCIe 协议栈中的不同层次&#xff0c;具体如下&#xff1a; TLP 发送阶段 1&#xff08;TS1&#xff09;&#xff1a;这个阶段是在传输层&#xff08;Transaction Layer&#xff09;中进行的。在这个阶段&#xff0c;TLP 数据包会进…

轻松应对大数据挑战!利用ETLCloud实现TDengine数据库的高效查询与数据迁移

TDengine 是一款开源、云原生的时序数据库&#xff0c;专为物联网、工业互联网、金融、IT 运维监控等场景设计并优化。它能让大量设备、数据采集器每天产生的高达 TB 甚至 PB 级的数据得到高效实时的处理&#xff0c;对业务的运行状态进行实时的监测、预警。 根据TDengine文档…

算法--递归--基础

定义 计算机科学中&#xff0c;递归是一种解决计算问题的方法&#xff0c;其中解决方案取决于同一类问题的更小子集 递归是一种非常高效、简洁的编码技巧&#xff0c;一种应用非常广泛的算法。 如求100以内的和 那么就等同于求10099以内的和 99以内和等同于9998以内的和 … 依…

复杂SQL优化实例

SQL语句的执行顺序&#xff1a; 执行计划指标查看 优化实例一 LIMIT 语句 分页查询是最常用的场景之一&#xff0c;但也通常也是最容易出问题的地方。比如对于下面简单的语句&#xff0c;一般 DBA 想到的办法是在 type, name, create_time 字段上加组合索引。这样条件排序都能…

面对市面上众多的商城系统,我们该如何选择?

数字化时代&#xff0c;传统的实体店铺发展进入瓶颈。越来越多的消费者选择在网上购物&#xff0c;这也催生了各种各样的电商平台和商城系统&#xff0c;如SHOP、Magento等。但是&#xff0c;对于那些想要进入电子商务领域的企业来说&#xff0c;如何选择适合自己的商城系统&am…

[BigGAN] Large Scale GAN Training for High Fidelity Natural Image Synthesis

1、目的 在大型数据集上训练class-conditional GAN&#xff0c;并探索相关的trick 2、贡献 1&#xff09;数据集的扩大使得GAN的表现也随之提升。文章的网络参数量是之前工作的2~4倍&#xff0c;batch size是之前的8倍。文章分别从两方面对performance进行提升&#xff1a;sca…

计算机视觉:语义分割理论及实战

语义分割 语义分割&#xff08;Semantic Segmentation&#xff09;是指将一张图像分割成若干个区域&#xff0c;并对每个区域赋予语义标签的任务。它是计算机视觉中的一种重要技术&#xff0c;被广泛应用于自动驾驶、医学图像分析、地理信息系统等领域。 与传统的图像分割任务…

奇安信应急响应-Linux

Linux需要经常关注的目录 /etc/passwd用户信息文件&#xff1a;我们需要看一下里面到底是什么&#xff0c;保存的用户信息 /etc/rc.d/rc.loacl&#xff1a;开机启动项&#xff1a;类似于Windows的开机启动项&#xff0c;有可能攻击者会在里面写一个后门文件&#xff0c;需要重…