这片土地的旧时光 · 详解 C++98 与新版 C++ 的不同

C++ 是一门历史悠久的语言。从 1983 年 Bjarne Stroustrup 发明它开始,到 1998 年 ISO 正式标准化(C++98),再到如今的 C++23,这门语言经历了翻天覆地的变化。

如果你曾经接触过老派的 C++ 教材,或者维护过年代久远的代码库,可能会发现它们与现代 C++ 有着天壤之别。让我们来看看,这片土地上发生过怎样的沧桑巨变。


内存管理的进化

在 C++98 时代,动态内存管理是一场噩梦:

// C++98 风格:手动管理内存
class OldStyle
{
    int* data;
public:
    OldStyle() : data(new int[100]) {}
    ~OldStyle() { delete[] data; }
    
    // 必须手动实现拷贝构造和赋值,否则会 double free!
    OldStyle(const OldStyle& other) : data(new int[100])
    {
        for (int i = 0; i < 100; ++i)
            data[i] = other.data[i];
    }
    
    OldStyle& operator=(const OldStyle& other)
    {
        if (this != &other)
        {
            delete[] data;
            data = new int[100];
            for (int i = 0; i < 100; ++i)
                data[i] = other.data[i];
        }
        return *this;
    }
};

现代 C++ 使用智能指针,一切变得简单:


auto_ptr 的消亡

C++98 有一个叫 auto_ptr 的智能指针,但它有严重的设计缺陷:

C++11 废弃了 auto_ptr,引入了语义清晰的智能指针家族:


类型推断的革命

C++98 要求显式写出所有类型:

C++11 引入 auto 关键字,代码变得简洁:


初始化的统一

C++98 的初始化方式混乱不堪:

C++11 统一使用花括号初始化:


范围 for 循环

遍历容器在 C++98 中很繁琐:

C++11 的范围 for 循环简洁明了:


nullptr 的引入

C++98 使用 NULL0 表示空指针,这会导致重载歧义:

C++11 引入类型安全的 nullptr


移动语义的诞生

C++98 没有移动语义,复制临时对象非常低效:

C++11 的移动语义避免了不必要的复制:


Lambda 表达式

C++98 需要为每个简单操作定义函数对象:

C++11 的 lambda 让一切变得简单:


constexpr:编译期计算

C++98 的编译期计算只能通过模板元编程:

C++11/14 的 constexpr 让编译期计算变得自然:


变参模板

C++98 处理可变数量参数非常困难:

C++11 的变参模板优雅地解决了这个问题:


总结:旧时光与新纪元

特性
C++98
现代 C++

内存管理

new/delete 手动管理

智能指针自动管理

类型声明

完全手写

auto 自动推断

空指针

NULL0

nullptr

初始化

多种语法

统一的 {} 语法

循环

迭代器

范围 for

函数对象

手写类

lambda 表达式

编译期计算

模板元编程

constexpr

移动语义

右值引用

现代 C++ 不仅仅是语法上的改进,更是编程理念的革新。它让 C++ 从一门"专家语言"变成了一门更加安全、高效、易用的语言。

如果你还在使用 C++98 风格编程,是时候拥抱现代 C++ 了!

Last updated