C 与 C++:一对父子的渐行渐远

Posted on Sat 17 January 2026 in Programming

"C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off." —— Bjarne Stroustrup


开篇:你以为的 C++,可能已经是"古董"了

如果你是 90 后程序员,你学 C++ 的时候,教材上写的可能还是 C++98。

那时候的 C++,确实像是"C with Classes"——多了个 class,多了个 new/delete,多了个虚函数,仅此而已。

但如果你现在还抱着这种认知,看到一段现代 C++ 代码,你可能会怀疑人生:

auto result = std::ranges::views::filter(numbers, [](int n) { return n > 0; })
            | std::ranges::views::transform([](int n) { return n * 2; });

这是 C++ 吗?怎么看起来像 Python 和 Rust 的私生子?

没错,这就是现代 C++(C++20)

今天,我们就来聊聊: 1. C 和 C++ 到底有哪些本质区别? 2. 从 C++11 到 C++23,这门语言经历了怎样的"文艺复兴"? 3. 作为开发者,我们该怎么跟上这趟"现代化列车"?


一、C 和 C++:设计哲学的分道扬镳

1.1 C:信任程序员,给你一把手术刀

C 语言的设计哲学是:程序员知道自己在做什么

它提供了最底层的控制能力——指针、内存、位操作。它不会阻止你做任何事情,包括把自己炸死。

// C 语言:我相信你
int* p = (int*)malloc(100);  // 可能返回 NULL
*p = 42;                      // 如果 p 是 NULL,炸了
free(p);
*p = 0;                       // Use after free,炸了

C 的优点是简单、透明、可预测。你写什么,编译器就生成什么,没有隐藏的魔法。

1.2 C++:我帮你管,但你得学我的规矩

C++ 的设计哲学是:零成本抽象(Zero-cost Abstraction)

它想给你更高级的抽象(类、模板、RAII),但又不想牺牲性能。结果就是——语言变得极其复杂。

// C++ 语言:我帮你管资源
auto p = std::make_unique<int>(42);  // 自动管理内存
// 离开作用域自动释放,不用操心

C++ 的优点是更安全、更高效(在正确使用的前提下)。缺点是学习曲线陡峭,坑多。

1.3 核心差异一览

特性 C C++
编程范式 过程式 过程式 + 面向对象 + 泛型 + 函数式
内存管理 手动 (malloc/free) 手动 + RAII + 智能指针
类型系统 弱类型检查 强类型检查 + 模板
异常处理 无(靠返回值) 有 (try/catch/throw)
函数重载 不支持 支持
命名空间 有 (namespace)
标准库 极简(stdio, stdlib) 丰富(STL, ,
编译速度 慢(尤其是模板多的时候)

二、代码对比:同一个问题,两种写法

场景:读取文件,统计单词频率

C 语言版本

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define MAX_WORD_LEN 100
#define MAX_WORDS 10000

typedef struct {
    char word[MAX_WORD_LEN];
    int count;
} WordCount;

WordCount words[MAX_WORDS];
int word_count = 0;

int find_word(const char* word) {
    for (int i = 0; i < word_count; i++) {
        if (strcmp(words[i].word, word) == 0) return i;
    }
    return -1;
}

void add_word(const char* word) {
    int idx = find_word(word);
    if (idx >= 0) {
        words[idx].count++;
    } else if (word_count < MAX_WORDS) {
        strcpy(words[word_count].word, word);
        words[word_count].count = 1;
        word_count++;
    }
}

int main() {
    FILE* f = fopen("input.txt", "r");
    if (!f) { perror("fopen"); return 1; }

    char word[MAX_WORD_LEN];
    while (fscanf(f, "%99s", word) == 1) {
        // 转小写
        for (char* p = word; *p; p++) *p = tolower(*p);
        add_word(word);
    }
    fclose(f);

    for (int i = 0; i < word_count; i++) {
        printf("%s: %d\n", words[i].word, words[i].count);
    }
    return 0;
}

现代 C++ 版本(C++17)

#include <iostream>
#include <fstream>
#include <map>
#include <string>
#include <algorithm>
#include <cctype>

int main() {
    std::ifstream file("input.txt");
    if (!file) { std::cerr << "Cannot open file\n"; return 1; }

    std::map<std::string, int> word_count;
    std::string word;

    while (file >> word) {
        // 转小写
        std::transform(word.begin(), word.end(), word.begin(),
                       [](unsigned char c) { return std::tolower(c); });
        word_count[word]++;
    }
    // file 自动关闭(RAII)

    for (const auto& [w, count] : word_count) {  // C++17 结构化绑定
        std::cout << w << ": " << count << '\n';
    }
}

差异对比

方面 C C++
代码行数 ~50 行 ~25 行
内存管理 手动定义数组大小 std::map 自动扩容
资源释放 手动 fclose RAII 自动释放
查找复杂度 O(n) 线性查找 O(log n) 红黑树
可读性 需要理解底层实现 意图更清晰

三、现代 C++ 的"文艺复兴"(C++11 到 C++23)

从 C++11 开始,C++ 标准委员会终于开窍了——他们不再只顾着加复杂的元编程特性,而是开始关注易用性安全性

3.1 C++11:革命的起点

这是现代 C++ 的元年。如果你只能学一个版本,学 C++11。

特性 说明 示例
auto 类型推导 auto x = 42;
智能指针 自动内存管理 std::unique_ptr, std::shared_ptr
Lambda 匿名函数 [](int x) { return x * 2; }
nullptr 类型安全的空指针 替代 NULL
范围 for 简化遍历 for (auto& item : container)
移动语义 避免不必要的拷贝 std::move()
右值引用 支持移动语义 T&&
constexpr 编译期计算 constexpr int fib(int n) {...}
// C++11 之前
std::vector<int>::iterator it = vec.begin();
for (; it != vec.end(); ++it) { ... }

// C++11 之后
for (auto& item : vec) { ... }

3.2 C++14/17:小步快跑

版本 关键特性
C++14 泛型 Lambda、auto 返回类型推导、std::make_unique
C++17 if constexpr、结构化绑定、std::optionalstd::variantstd::filesystem
// C++17 结构化绑定
std::map<std::string, int> scores = {{"Alice", 90}, {"Bob", 85}};
for (const auto& [name, score] : scores) {
    std::cout << name << ": " << score << '\n';
}

// C++17 std::optional
std::optional<int> find_value(int key) {
    if (key == 42) return 100;
    return std::nullopt;  // 明确表示"没有值",比返回 -1 安全
}

3.3 C++20:质的飞跃

C++20 是自 C++11 以来最大的一次更新。它引入了四大特性:

  1. Concepts(概念):给模板加约束,编译错误终于能看懂了
  2. Ranges(范围):函数式风格的数据处理
  3. Coroutines(协程):原生异步支持
  4. Modules(模块):替代 #include,加速编译
// Concepts:让模板错误信息变得人类可读
template<typename T>
concept Addable = requires(T a, T b) { a + b; };

template<Addable T>
T add(T a, T b) { return a + b; }

// Ranges:管道式数据处理
#include <ranges>
auto result = numbers 
    | std::views::filter([](int n) { return n > 0; })
    | std::views::transform([](int n) { return n * 2; });

// Coroutines:异步生成器
generator<int> fibonacci() {
    int a = 0, b = 1;
    while (true) {
        co_yield a;
        auto tmp = a;
        a = b;
        b = tmp + b;
    }
}

3.4 C++23:持续打磨

C++23 没有 C++20 那么"革命",但也有不少实用改进:

特性 说明
std::expected std::optional 更好的错误处理,类似 Rust 的 Result
std::print / std::println 终于有像样的格式化输出了(类似 Python 的 print)
std::mdspan 多维数组视图
import std; 标准库模块化
if consteval 区分编译期和运行期执行
// C++23: std::expected 错误处理
std::expected<int, std::string> parse_int(std::string_view s) {
    if (s.empty()) return std::unexpected("empty string");
    // ...
    return 42;
}

// C++23: std::print
std::print("Hello, {}!\n", "World");  // 终于不用 cout << 了

四、C++26 及未来:路在何方?

C++ 标准委员会目前正在推进 C++26,重点方向包括:

  1. 静态反射 (Static Reflection):在编译期获取类型信息,元编程的终极形态
  2. Contracts(契约):前置条件、后置条件、断言的标准化
  3. Pattern Matching(模式匹配):类似 Rust/Haskell 的 match 语法
  4. Executors(执行器):标准化的异步执行框架
// 可能的 C++26 模式匹配语法(提案中)
inspect (value) {
    0 => { return "zero"; }
    1 => { return "one"; }
    x if (x < 0) => { return "negative"; }
    _ => { return "other"; }
};

五、选 C 还是 C++?

这个问题没有标准答案,取决于你的场景:

场景 推荐 理由
嵌入式 / 裸机开发 C 资源受限,需要完全控制
操作系统内核 C Linux、Windows 内核都是 C
高性能服务器 C++ 需要抽象但不能牺牲性能
游戏引擎 C++ Unreal Engine、Unity 核心都是 C++
量化交易 C++ 低延迟 + 复杂业务逻辑
简单脚本 / 工具 都不推荐 用 Python/Go 吧

我的建议: - 如果你是 C 程序员,想提升抽象能力 → 学现代 C++ - 如果你是 Java/Python 程序员,想学底层 → 先学 C,再学 C++ - 如果你只想快速出活 → Rust 或 Go 可能是更好的选择


总结

概念 说明
C 简单、透明、危险的"手术刀"
C++ 强大、复杂、需要正确使用的"瑞士军刀"
C++11 现代 C++ 的起点,必学
C++17 实用特性最多的版本
C++20 革命性更新:Concepts, Ranges, Coroutines, Modules
C++23 持续打磨:std::expected, std::print

Checklist:升级到现代 C++ 的第一步

  • [ ] 把 new/delete 换成 std::make_unique / std::make_shared
  • [ ] 用 auto 减少冗长的类型声明
  • [ ] 用范围 for 替代迭代器 for
  • [ ] 用 Lambda 替代函数指针
  • [ ] 用 std::optional 替代"魔法值"(如 -1 表示无效)
  • [ ] 打开编译器的 C++17/20 标准:-std=c++20
  • [ ] 试着用 Ranges 重写一段数据处理代码

扩展阅读


本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。