第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
if (condition)
{
    // code
}
大括号独占一行,清晰易读
K&R
if (condition) {
    // code
}
紧凑,节省行数
Stroustrup
if (condition) {
    // code
}
类似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。

知识体系结构图

下面这张图,帮你梳理本章的核心知识点:

代码格式规范 缩进与对齐 4空格缩进 变量对齐声明 参数对齐 大括号风格 Allman风格 K&R风格 统一规范 空格与空行 运算符空格 逻辑块空行 函数间空行 行长度限制 80-100字符 运算符换行 参数换行 代码块组织 函数单一职责 类结构清晰 高内聚低耦合 统一规范 + 自动化工具 = 高质量代码

嗯,代码格式这事儿,说白了就是「约定大于配置」。你不需要记住所有细节,但你需要一个团队都认可的规范,然后用工具(比如 clang-format)自动执行。我见过太多团队,花大量时间在代码审查时争论「这里要不要空格」,这完全是在浪费生命。

记住:好的代码格式,不是为了好看,而是为了减少沟通成本、降低维护难度。你想想看,一个新人加入团队,打开代码一看,格式整齐、结构清晰,他上手的速度会快很多。反之,如果代码乱七八糟,他光适应格式就要花一周。

最后,送你一句话:代码是写给人看的,顺便给机器执行。所以,把格式做好,是对同事、对未来的自己,最大的善意。