前言
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::variant
、std::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
The End
参考资料