C++版本更新历史

前言

C++语言发展至今已经迭代了很多版本,而在不同环境中编写代码时经常看到C++标准的设定,比如 Leetcode 中可以看到版本信息:

这说明Leetcode已经支持最新C++23标准了,但某些环境并不一定支持这些语法,如果不清楚使用的语法属于哪个版本就盲目去写,将无法成功编译。本文整理了C++各个版本的常用特性方便查阅和学习。

起源

C++ 语言的发展史可以追溯到 1979 年,当时丹麦科学家 Bjarne Stroustrup 在贝尔实验室工作,为了提高软件开发的效率和灵活性,他开始为 C 语言添加类和面向对象编程的特性。这些早期的尝试被称为 "C with Classes"。在 1983 年,Stroustrup 将这个语言重新命名为 C++,这个名字由 Rick Mascitti 提出,意在表达这是 C 语言的一个继承和扩展。

C++98

C++98为C++语言制定了第一个官方标准 ,统一了不同编译器和平台之间的差异,提高了代码的可移植性和稳定性 。引入了STL,一套通用的模板 库,提供了丰富的数据结构和算法。还引入了异常处理 机制和命名空间的概念。

C++11

非常重要的一次版本更新,平时用的最多的语法和特性**(※)**基本都是C++11时就有的。

  • 自动类型推导:引入了**auto关键字**,可以根据初始化表达式自动推导出变量的类型 。
cpp 复制代码
auto x = 5;          // int
auto y = 5.0;        // double
auto z = "Hello";    // const char*

vector<int> v = {1, 2, 3, 4, 5};
for (auto it = v.begin(); it != v.end(); ++it) {
    cout << *it << " ";  // 使用auto推导迭代器类型
}
  • 范围for循环:引入了范围for循环的语法(元素:容器),遍历容器更简洁 。
cpp 复制代码
vector<int> v = {1, 2, 3, 4, 5};
for (auto n : v) {
    cout << n << " ";  // 直接遍历容器中的元素
}
  • 智能指针:引入了智能指针,可以自动管理内存资源 。
cpp 复制代码
#include <memory>
//std::unique_ptr 的设计初衷是确保资源的唯一所有权,以简化资源管理并避免内存泄漏。
//如果你需要共享资源,应该使用 std::shared_ptr。
//std:weak_ptr 用于解决shared_ptr可能导致的循环引用问题,不拥有资源,不增加引用计数。
unique_ptr<int> up(new int(10));
shared_ptr<int> sp(new int(20));
weak_ptr<int> wp = sp;
  • Lambda表达式:引入了Lambda表达式,可以方便地定义匿名函数对象 。
cpp 复制代码
auto lambda = [](int x, int y) {
    return x + y;
};

cout << "Sum: " << lambda(5, 10) << endl;  // 使用Lambda表达式计算和
  • 可变参数模板:允许模板函数或模板类接受不确定数量的模板参数,但是需要手动解参数包,通常涉及到递归。
cpp 复制代码
template<typename T, typename... Args>
void print(T first, Args... args) {
    cout << first << ", ";
    print(args...); // 递归调用
}
  • 并发编程支持:提供了对并发编程的支持,包括线程库、原子操作、互斥量等 。
cpp 复制代码
#include <thread>
thread t([]() {
    cout << "Hello, world!" << endl;
});

t.join();  // 等待线程t完成

C++14

  • 泛型Lambda 表达式:在Lambda表达式中使用auto关键字进行类型推导 。
cpp 复制代码
//匿名函数更加灵活
auto add = [](auto a, auto b) { return a + b; };
cout << add(5, 3) << endl;    // 输出 8
cout << add(3.14, 2.56) << endl; // 输出 5.7
  • 变量模板:可以定义模板化的变量,使得代码更加通用和可重用 。
cpp 复制代码
template<typename T>
constexpr T pi = T(3.14159265358979323846);
cout << pi<int> << endl;    // 输出 3
cout << pi<double> << endl;  // 输出 3.14159265358979323846
  • 放松的constexpr限制:允许在constexpr函数中使用更多的语言特性 。
cpp 复制代码
constexpr int factorial(int n) {
    return (n <= 1) ? 1 : (n * factorial(n - 1));
}
cout << factorial(5) << endl; // 输出 120,编译时计算
  • 二进制字面量:可以方便地表示二进制数值 。
cpp 复制代码
int binaryValue = 0b1101; // 表示二进制值1101,即十进制的13
cout << binaryValue << endl; // 输出 13

C++17

  • ※结构化绑定:可以方便地解构数据结构中的成员变量 。
cpp 复制代码
struct Point {
    int x, y;
};

int main() {
    Point p{1, 2};
    auto [x, y] = p; // 结构化绑定,解构Point结构体
    cout << x << ", " << y << endl; // 输出 1, 2
}
  • if constexpr语句:可以在编译时进行条件判断和优化 。
cpp 复制代码
template <typename T>
void doSomething(T value) {
    if constexpr (std::is_integral<T>::value) {
        cout << "T is an integral type" << endl;
    } else {
        cout << "T is not an integral type" << endl;
    }
}

int main() {
    doSomething(5);    // 编译时会选择执行is_integral分支
    doSomething(3.14); // 编译时会选择执行!is_integral分支
}
  • 折叠表达式:可以方便地对参数包进行展开和操作 。
cpp 复制代码
template <typename... Args>
int sum(Args... args) {
    return (0 + ... + args); // 折叠表达式,将所有参数相加
}

int main() {
    cout << sum(1, 2, 3, 4) << endl; // 输出 10
}
  • 新增算法和数据结构:如std::variantstd::optional
cpp 复制代码
#include <variant>
#include <optional>

std::variant<int, double, std::string> v = 42; // variant可以存储多种类型中的一个
std::optional<int> o = std::make_optional(10);  // optional用于表示可能为空的值

int main() {
    if (o) {
        cout << *o << endl; // 输出 10,如果o有值
    }

    std::visit([](auto&& arg) { cout << arg << endl; }, v); // 输出 42,使用std::visit来访问variant的值
}

C++20

  • 概念(Concepts):提供了编译时类型检查的功能 ,允许程序员定义一组约束,只有满足这些约束的类型才能作为模板参数。
cpp 复制代码
template<typename T>
concept Addable = requires(T a, T b) {
    { a + b } -> std::same_as<T>;
};

template<Addable T>
T add(T a, T b) {
    return a + b;
}
  • 协程(Coroutines):实现了轻量级的协程,为编写异步代码提供了便利 。
cpp 复制代码
#include <iostream>
#include <coroutine>

// 定义协程的返回对象
struct Task {
    struct promise_type {
        Task get_return_object() { return {}; }
        std::suspend_never initial_suspend() { return {}; }
        std::suspend_never final_suspend() noexcept { return {}; }
        void return_void() {}
        void unhandled_exception() {}
    };
};

Task myCoroutine() {
    // 在这里编写协程的逻辑
    std::cout << "Hello, ";
    std::coroutine::suspend_never one;
    std::coroutine::suspend_never two;
    std::coroutine::resume(one);
    std::coroutine::resume(two);
    std::cout << "World!" << std::endl;
}

int main() {
    myCoroutine();
}
  • 模块(Modules):改进了程序的单元隔离和增量编译 ,允许将代码组织成更小的、可维护的单元。模块可以提高编译速度,因为它们可以被编译器缓存和重用。
cpp 复制代码
// example.cppm
export module example;
export int add(int a, int b) { return a + b; }

// main.cpp
import example;

int main() {
    int result = add(3, 5);
    return result;
}
  • 范围(Ranges):为处理序列数据提供了统一的接口 。
cpp 复制代码
#include <iostream>
#include <ranges>
#include <vector>

int main() {
    std::vector<int> v = {5, 3, 9, 1, 6};

    // 使用自定义比较函数进行排序
    std::ranges::sort(v, std::greater<>{});

    for (int n : v) {
        std::cout << n << ' ';
    }
    std::cout << '\n'; // 输出排序后的向量:9 6 5 3 1
}
  • 标准库增强:添加了一些新的特性,如span ,它提供了一种轻量级的方式来表示连续内存区域的一段区间,本身不拥有它所指向的内存,只是提供了一种访问内存的方式。

C++23

C++前沿开发 - 腾讯云开发者社区


The End

参考资料

cppreference中文

现代 C 与 C++ 开发基础

相关推荐
程序员如山石4 分钟前
Qt的互斥量用法
开发语言·qt
终末圆13 分钟前
MyBatis—Plus 快速上手【后端 22】
java·开发语言·数据库·后端·sql·spring·mybatis
fareast_mzh27 分钟前
eMule allows you to optimize your queue and sharing efficiency
java·开发语言·数据库
牵牛老人37 分钟前
Qt开发技巧(九)去掉切换按钮,直接传样式文件,字体设置,QImage超强,巧用Qt的全局对象,信号槽断连,低量数据就用sqlite
开发语言·qt·sqlite
聆听HJ44 分钟前
java 解析excel (本地资源)
java·开发语言·excel
不拱地的猪44 分钟前
想知道为什么有DICOM格式,YAML格式,XML格式,JSON格式吗?
xml·java·c++·opencv·json
yi碗汤园1 小时前
【一文读懂】C#如何实现通用的排序功能
开发语言·数据结构·算法·c#
peihexian1 小时前
使用rust实现rtsp码流截图
开发语言·后端·rust
AutoAutoJack1 小时前
C# 字符串(String)的应用说明一
开发语言·数据结构·算法·架构·c#
master cat1 小时前
C++中数据类型的大小
开发语言·c++