4. 代码格式
代码格式这事儿,说大不大,说小不小。我见过不少团队,技术能力很强,但代码一打开,缩进乱七八糟,大括号满天飞,看着就头疼。说白了,格式是代码的「脸面」。你想想看,一个连脸都洗不干净的程序员,谁敢相信他写的逻辑没问题?
这一章,我就把代码格式的几个核心点掰开揉碎了讲。包括缩进与对齐、大括号风格、空格与空行、行长度限制、代码块组织。这些都是我多年实战中踩过坑、总结出来的经验。
4.1 缩进与对齐:别让代码「歪七扭八」
缩进是代码结构的第一道防线。我个人习惯用4个空格,不用Tab。为什么?因为不同的编辑器对Tab的解析不一样,有的显示2格,有的显示8格,一换环境代码就崩了。用空格,稳得很。
核心原则:同一层级的代码,缩进必须一致。嵌套层级每深一层,缩进增加4个空格。
// 好的缩进示例
void ProcessData(const std::vector<int>& data) {
for (size_t i = 0; i < data.size(); ++i) {
if (data[i] > 0) {
std::cout << "Positive: " << data[i] << std::endl;
}
}
}
// 坏的缩进示例
void ProcessData(const std::vector<int>& data) {
for (size_t i = 0; i < data.size(); ++i) {
if (data[i] > 0) {
std::cout << "Positive: " << data[i] << std::endl;
}
}
}
对齐呢?我建议在变量声明、函数参数、赋值操作中,适当使用对齐来提升可读性。但别过度,否则维护起来很痛苦。
// 对齐示例
int count = 0;
double total = 0.0;
std::string name = "hello";
// 函数参数对齐
void DrawRect(int x, int y,
int width, int height);
小技巧:如果你用VS Code或CLion,可以配置保存时自动格式化。我一般用 clang-format,统一团队风格,省心省力。
4.2 大括号风格:选一种,然后坚持到底
大括号风格是C++社区的老话题了。我个人偏爱 Allman 风格,也就是大括号独占一行。为什么?因为这样能清晰地看到每个作用域的起止位置,尤其当嵌套很深时,眼睛不容易看花。
但我也见过很多团队用 K&R 风格,大括号跟在语句后面。这也没问题,关键是——统一。我曾经在一个项目里,看到同一个文件里三种大括号风格混用,那叫一个酸爽。
| 风格名称 | 示例 | 特点 |
|---|---|---|
| Allman | |
大括号独占一行,清晰易读 |
| K&R | |
紧凑,节省行数 |
| Stroustrup | |
类似K&R,但else另起一行 |
避坑指南:我曾经在一个遗留项目中,看到有人把大括号写在行尾,但函数体的大括号又独占一行。这种混搭风格,代码审查时被骂得狗血淋头。记住:选一种风格,写到项目规范里,所有人都遵守。
4.3 空格与空行:呼吸感很重要
代码也需要「呼吸」。没有空格的代码,就像一堵密不透风的墙。我建议在以下位置加空格:
- 二元运算符两侧:
a + b,而不是a+b - 逗号后面:
func(a, b, c),而不是func(a,b,c) - 关键字后面:
if (condition),而不是if(condition) - 大括号内部:
{ 1, 2, 3 },而不是{1,2,3}
空行呢?我一般这样用:
- 函数之间:空一行
- 逻辑块之间:空一行,比如变量声明和业务逻辑之间
- 类定义内部:成员函数之间空一行,不同访问权限块之间空一行
// 好的空行与空格示例
class Calculator {
public:
Calculator() = default;
int Add(int a, int b) {
return a + b;
}
int Subtract(int a, int b) {
return a - b;
}
private:
int result_ = 0;
};
void Process() {
int x = 10;
int y = 20;
// 计算逻辑
int sum = x + y;
std::cout << "Sum: " << sum << std::endl;
}
个人经验:我习惯在函数内部,变量声明和业务逻辑之间空一行。这样一眼就能看出「这是准备阶段」和「这是执行阶段」。代码审查时,这种小细节很加分。
4.4 行长度限制:别让代码「跑出屏幕」
行长度限制,说白了就是别让代码太长,导致横向滚动条出现。我建议每行不超过80个字符,最多100个。为什么是80?因为很多终端、代码审查工具、并排对比窗口,宽度就那么多。
如果一行太长,怎么办?换行呗。但换行也有讲究:
- 在运算符处换行,运算符放在行首
- 函数参数换行时,对齐到第一个参数
- 三元运算符换行时,问号和冒号放在行首
// 好的换行示例
void DrawRectangle(int x, int y,
int width, int height,
Color color, bool filled) {
// code
}
// 三元运算符换行
int result = (condition)
? value_if_true
: value_if_false;
避坑指南:我曾经接手过一个项目,有人把一长串字符串拼接写在一行里,超过300个字符。我改bug时,根本看不清字符串里有什么。后来我强制要求:字符串拼接也要换行,每行一个字符串片段,用加号连接。
4.5 代码块组织:让逻辑「一目了然」
代码块组织,说白了就是怎么把代码「分组」。我建议:
- 每个函数只做一件事,函数体不超过50行
- if-else 块中,如果某个分支超过3行,就用大括号括起来
- 循环体内部,如果超过5行,考虑提取成函数
- 类定义内部,按「公有接口 -> 保护方法 -> 私有方法 -> 成员变量」的顺序组织
// 好的代码块组织示例
class FileManager {
public:
// 公有接口
bool OpenFile(const std::string& path);
void CloseFile();
std::string ReadLine();
protected:
// 保护方法
virtual void OnFileOpened();
private:
// 私有方法
bool ValidatePath(const std::string& path);
// 成员变量
std::ifstream file_stream_;
std::string current_path_;
};
核心原则:代码块组织要遵循「高内聚、低耦合」。同一个功能模块的代码放在一起,不同功能的代码用空行或注释隔开。我见过最糟糕的代码,一个函数里既有文件读写,又有网络请求,还有UI更新。这种代码,改一个bug能引出三个新bug。
知识体系结构图
下面这张图,帮你梳理本章的核心知识点:
嗯,代码格式这事儿,说白了就是「约定大于配置」。你不需要记住所有细节,但你需要一个团队都认可的规范,然后用工具(比如 clang-format)自动执行。我见过太多团队,花大量时间在代码审查时争论「这里要不要空格」,这完全是在浪费生命。
记住:好的代码格式,不是为了好看,而是为了减少沟通成本、降低维护难度。你想想看,一个新人加入团队,打开代码一看,格式整齐、结构清晰,他上手的速度会快很多。反之,如果代码乱七八糟,他光适应格式就要花一周。
最后,送你一句话:代码是写给人看的,顺便给机器执行。所以,把格式做好,是对同事、对未来的自己,最大的善意。