注释的类型
注释是插入在代码中的、用来解释程序的一行或多行文字,C++中有两种注释。
一是以//开始的单行注释,告诉编译器忽略这一行中//之后的所有内容。例如:
std::cout << "Hello world!"; // 本行从这开始的内容会被忽略.
通常,单行注释用来对单行进行简短的注释。
std::cout << "Hello world!" << std::endl; // cout、endl来自输入输出库
std::cout << "It is very nice to meet you!" << std::endl; //这些注释让程序变得难以阅读
std::cout << "Yeah!" << std::endl; //尤其当每行长度不一致时
把注释和程序放在同一行会让代码和注释都变得难以阅读,如果一行比较长时这种情况更为严重,所以//注释最好放在要注释的那一行上面,如下:
// cout、endl来自输入输出库
std::cout << "Hello world!" << std::endl;
// 这样更易于阅读
std::cout << "It is very nice to meet you!" << std::endl;
// 你觉得呢?
std::cout << "Yeah!" << std::endl;
符号对是延续了C语言风格的多行注释,符号对之间的一切都会被编译器忽略。
由于注释符之间的一切都会被忽略,所以有时你也会看到这种美化版的注释。
多行注释不允许嵌套,否则会产生意料不到的结果。例如:
此处内同不在注释中 */
// 上述注释在第一个*/处就结束了,而不是期望的第二个
(译者注:此处编译器会匹配原则,遇到第一个,并忽略它们之间的内容,上述注释的实际效果可从高亮的代码上看出)
规范:多行注释不允许嵌套
合理地使用注释
通常在三种情况下会使用注释,用来描述库、函数和程序的功能。例如:
// 本程序的功能是根据学生的考试成绩和作业情况计算最终得分
// 此函数的功能是使用牛顿法计算方程的近似根。
// 下面几行代码根据权重和级别产生随机项。
以上注释让读者在没有阅读所有代码的情况下就对程序的功能有了大致的了解,用户(也可能是团队成员或其他人,或当你想重用之前写的代码时)一眼就能看出程序是否符合其需求,这一点在团队合作时尤为重要,因为每个成员都不会了解全部的代码。
除了描述功能,注释也可以用来描述代码是如何实现这个功能的。
// 为了得到随机项,进行以下几步工作
// 1) 将所有可能项置于列表中
// 2) 根据权重与等级计算每一项的概率
// 3) 选择一个随机数
// 4) 指出该随机数对应的项
// 5) 返回结果
这些注释也只需向用户传递基本实现思路,而不需关注太多细节。
语句级别的注释应该用来描述代码为什么这样写,而不是描述代码干了什么,如果你写出了一个相当复杂的语句以至于不注释就没人看得懂,那你一般需要重写代码而不是添加注释。以下是几个优劣注释的示例。
差注释:
// 把sight赋值为0
sight = 0;
显而易见的东西何必注释?
好注释:
// 玩家中了失明药水,所以视野为0
sight = 0;
这让我们知道为什么将视野设置为0.
差注释:
// 计算物品的花销
cost = items / 2 * storePrice;
我们一看就知道这是计算cost的,但我们真正需要知道的是为什么把items除以2呢?
好注释:
// 把items除以2是因为它都是成对买的
cost = items / 2 * storePrice;
这样我们就知道了。
程序员常在解决问题的多个方法之间进行艰难抉择,注释是提醒自己或别人为何使用这种方法的伟大方式。
好注释:
//我们决定使用链表而不是数组
//因为数组做插入操作效率太低
//我们使用牛顿法来求方程的近似跟
//因为找不到更好的算法
(译者注:这让我想起我们大学的数值分析老师常说牛顿法是世界上最牛逼的算法,任何好的算法都要跟牛顿法扯点关系,哈哈哈)
最后,注释应当用来让不了解你代码的人了解你的程序是干什么的,程序员会说:这不是显而易见的嘛,我怎么都不会忘记的。真的如此吗?显然不是,你很快就会发现你的遗忘速度超乎你的想象。阅读单独几行代码确实很容易,但要整体把握一堆代码的功能就是一件难事了。
总结一下:
- 在程序级、函数级、库级,描述是什么?
- 库、程序、函数中,描述怎么做?
- 语句级别上,描述为什么?
注释掉代码
将一行或多行代码转换成注释称为注释掉代码,这提供了一种方式(暂时的)将部分代码排除在编译的部分之外。
可以简单地使用//将一行代码转换为注释:
未注释掉:
std::cout << 1;
注释掉:
// std::cout << 1;
如果要注释掉一段代码,可以使用多个//或一对,例如:
未注释掉:
std::cout << 1;
std::cout << 2;
std::cout << 3;
使用//注释掉
// std::cout << 1;
// std::cout << 2;
// std::cout << 3;
使用注释掉
/*
std::cout << 1;
std::cout << 2;
std::cout << 3;
*/
这么做的原因可能有以下几种:
- 你正在编写一段新的代码但尚未完成,而此时你需要运行程序。有编译错误的情况下程序是不允许运行的,可暂时注释掉那部分代码以使程序得以运行,之后你还可以继续之前的工作。
- 你写好的代码编译通过但运行出错,你现在没时间解决这个问题,注释掉出问题的代码可以保证那部分不运行并产生错误,直到有时间解决。
- 为了找到错误的来源,如果程序产生了非预期结果或者崩溃了,尝试注释掉部分代码可以隔离导致程序出错的部分。如果你注释掉某行或某几行代码后,程序产生预期结果或不在崩溃,那么问题就出在你注释掉的这部分代码上,你可以专注解决这部分存在的问题。
- 如果你想用一段新的代码替换旧代码而不想删除旧代码(留着有用),就可以注释掉旧代码,直到确定新代码可以正常工作再删除掉。如果新代码不能正常工作,你随时可以删除新代码,换回原来的代码。
做开发时注释掉代码是常见的事,许多IDE也都提供了注释掉一段高亮代码的功能,如何使用取决于IDE。(VisualStudio中可在Edit->Advanced->Comment Selection/UncommentSelection(编辑->高级->注释选定内容/取消注释选定内容)找到。
关于本教程的注释
本系列教程的其余部分,我会用注释解释代码块是如何工作的。精明的读者会注意到,这些注释都是十分糟糕的。在之后的学习中,注意这些注释都是为了教学用的,而不是优秀注释的展示。