C++发展

目录

​编辑C++ 的发展总结:​编辑

1. C++ 的早期发展(1979-1985)

2. C++ 标准化过程(1985-1998)

3. C++ 标准演化(2003-2011)

4. C++11(2011年)

5. C++14(2014年)

6. C++17(2017年)

7. C++20(2020年)

8. C++23(2023年)

1. C++ 1985: C++ 1.0

主要特性:

示例代码:

代码讲解:

C++ 1.0 的局限性:

总结:

2. C++ 1989: C++ 2.0

主要特性:

多重继承与虚继承

示例代码:

代码讲解:

运行输出:

解释:

C++ 2.0 的局限性:

总结:

3. C++ 1990: C++ 3.0

主要特性:

模板的引入

示例代码:模板示例

代码讲解:

运行输出:

代码解释:

模板的优势:

C++ 3.0 的局限性:

总结:

4. C++ 1998: C++98

主要特性:

示例代码:C++98 的常见特性

代码讲解:

运行输出:

代码解释:

C++98 的局限性:

总结:

5. C++ 2003: C++03

主要特性和变化:

C++03 与 C++98 的区别:

示例代码:C++98 和 C++03 的差异

示例代码:模板特化修复和 SFINAE 改进

代码解释:

运行输出:

C++03 与 C++98 的局限性:

总结:

6. C++ 2011: C++11

主要新特性:

示例代码:C++11 特性

代码解释:

运行输出:

C++11 的优势:

C++11 的局限性:

总结:

7. C++ 2014: C++14

主要新特性:

示例代码:C++14 新特性

代码解释:

运行输出:

C++14 的优势:

C++14 的局限性:

总结:

8. C++ 2017: C++17

1. 结构化绑定声明 (Structured Bindings)

示例:

2. if/else语句中的初始化语句 (If/else with initialization)

示例:

3. std::optional

示例:

4. std::string_view

示例:

5. std::filesystem

示例:

6. 并行算法 (Parallel Algorithms)

示例:

7. 内联变量 (Inline Variables)

示例:

8. 改进的constexpr

示例:

总结

9. C++ 2020: C++20

1. 概念 (Concepts)

示例:

2. 范围 (Ranges)

示例:

3. 协程 (Coroutines)

示例:

4. 三向比较 (Spaceship Operator <=>)

示例:

5. 模块 (Modules)

示例:

6. 范围循环 (Range-based for loop with initializer)

示例:

7. std::span

示例:

8. consteval 和 constinit

示例:

总结

10. C++ 2023: C++23

1. 改进的常量表达式(constexpr)

示例:

2. std::expected

示例:

3. 范围(Ranges)库增强

示例:

4. std::format 改进

示例:

5. explicit 改进

示例:

6. std::span 支持的改进

示例:

7. 新的属性([[likely]] 和 [[unlikely]])

示例:

总结

​编辑

C++ 的发展总结:

C++ 是由 Bjarne Stroustrup 于 1979 年在贝尔实验室(Bell Labs)开始开发的,最初是作为 C 语言的一个扩展,目的是在不丧失 C 语言高效性的基础上,提供面向对象编程的特性。C++ 的发展历程可以分为以下几个重要阶段:

C++ 的早期发展1979-1985
C++ 标准化过程1985-1998
C++ 标准演化2003-2011
C++112011年
C++142014年
C++172017年
C++202020年
C++232023年

1. C++ 的早期发展(1979-1985)

  • 1979年:C++ 的前身 "C with Classes" 出现。Bjarne Stroustrup 在贝尔实验室的工作中,设计了一个扩展 C 语言的工具,该工具为 C 语言增加了类(class)、构造函数和析构函数等面向对象特性。它的设计目标是提高程序的可重用性,并通过封装数据和方法的方式增强程序结构。
  • 1983年:C with Classes 更名为 **C++**,并发布了第一版 C++ 语言,开始引入类、继承、多态等面向对象的特性,虽然这些特性并不完善,但已经为后来的发展奠定了基础。
  • 1985年:C++ 语言的第一个标准版本发布。Stroustrup 为此编写了《C++ Programming Language》一书,详细介绍了 C++ 的语法、特性和编程模型。

2. C++ 标准化过程(1985-1998)

  • 1989年:C++ 的第一个国际标准草案发布,作为一种较为成熟的语言,逐渐被越来越多的开发者使用。
  • 1990年:C++ 被纳入国际标准化组织(ISO)的标准化过程。这个过程中,C++ 逐步加入了更多的语言特性,如模板、异常处理、名字空间等。
  • 1998年:C++98 标准发布,这是 C++ 语言的第一个正式标准版本。C++98 通过增加模板支持、标准库(如 STL)和异常处理机制,使得 C++ 语言更加全面和功能强大,成为当时最主流的编程语言之一。

3. C++ 标准演化(2003-2011)

  • 2003年:C++03 标准发布,主要是对 C++98 标准的修正和小幅改进,修复了一些语言特性中的小错误,并未引入重大的新特性。
  • 2007年:ISO 发布了 C++0x 标准草案,该标准最终演变为 C++11。在 C++0x 的过程中,许多新的特性开始得到提出和采纳,如 自动类型推导右值引用lambda 表达式并发编程 等。C++11 的标准化过程历时多年,经历了大量的讨论和修改。

4. C++11(2011年)

  • 2011年:C++11 正式发布,它是 C++ 语言的一个重大变革,包含了大量的新特性,标志着 C++ 语言进入了一个全新的时代。C++11 的主要特性包括:
    • 自动类型推导auto);
    • 右值引用移动语义&&std::move);
    • Lambda 表达式
    • 线程支持std::thread);
    • 智能指针std::unique_ptrstd::shared_ptr);
    • 类型推导decltype)等。
  • C++11 的引入极大提升了 C++ 语言的表达力和现代化程度,使得 C++ 编程更具灵活性和高效性。

5. C++14(2014年)

  • 2014年:C++14 发布,相较于 C++11,C++14 更像是一个小规模的优化和修复版本。C++14 主要增强了 C++11 中的特性,如 Lambda 表达式的泛型支持、std::make_unique 的引入、decltype(auto) 的改进等。此外,还修复了一些编译器和实现中的问题。
  • C++14 让 C++11 中的很多新特性变得更加稳定,增加了可编程性和工具支持。

6. C++17(2017年)

  • 2017年:C++17 发布,这个版本包含了一些有意义的语言特性和标准库增强。主要特性包括:
    • **std::optional**:用于表示可能为空的值;
    • 结构化绑定声明auto [a, b] = tuple;);
    • if 和 switch 中的初始化语句
    • **std::filesystem**:用于处理文件和目录的标准库;
    • **改进的 std::string 和 std::array**;
    • 并行算法std::for_each 等支持并行执行)。
  • C++17 不仅增强了语言本身的功能,还进一步加强了对现代硬件和多核处理器的支持,增强了性能和并行计算能力。

7. C++20(2020年)

  • 2020年:C++20 发布,是 C++ 语言历史上一个非常重要的版本,带来了许多令人兴奋的新特性:
    • 模块(Modules):改善头文件管理,减少编译时间;
    • 三方比较操作符<=>): 用于自动生成比较操作符(比如 ==!=<<=>>=);
    • 协程(Coroutines):使得异步编程更加简洁;
    • 概念(Concepts):提供更强的类型约束机制,使模板编程更加安全;
    • 范围 for 循环改进:更简洁的语法和强大的灵活性;
    • **std::span**:处理数组和内存块的轻量级对象;
    • 改进的标准库:包括 std::formatstd::rangesstd::calendar 等。
  • C++20 为 C++ 带来了大量的现代化特性,并进一步提升了语言的表达能力、性能和并发编程的支持。

8. C++23(2023年)

  • 2023年:C++23 发布,虽然其变化相较于 C++20 比较平稳,但仍然包含了一些重要的改进和修复:
    • 新的标准库功能:例如,std::expectedstd::generator 和 std::ranges 的进一步改进;
    • 语言增强:对模板和类型推导的改进,增强了语言的灵活性和可读性;
    • 性能优化:进一步增强编译器对并行、异步和内存管理的支持。
  • C++23 标志着 C++ 语言持续向现代化发展,并且对性能和并发编程的支持进一步加强。
  1. 从面向过程到面向对象:最初的 C++ 语言只是在 C 语言的基础上增加了类和面向对象的特性,经过多年发展,C++ 在保留 C 语言高效性的同时,也吸收了面向对象、泛型编程和函数式编程的优势,成为了一门多范式的语言。

  2. 标准化过程:从 C++98 到 C++11,再到 C++14、C++17 和 C++20,C++ 逐渐成为一种具有广泛应用的编程语言,每个版本都带来了一些新的特性和增强,逐步适应现代软件开发的需求。

  3. 现代化与性能:C++ 在引入面向对象特性后,也逐步加入了并行计算、内存管理、泛型编程、协程等现代编程特性,使得它在高性能计算、系统开发、游戏开发和金融等领域仍然占有一席之地。

C++ 的发展历程体现了它强大的灵活性和持久生命力,C++ 不断演进,始终保持着与时俱进的能力,成为全球使用最广泛的编程语言之一。

C++ 的发展历程可以分为多个版本阶段,每个版本都带来了新的语言特性、库的改进和标准的增强。下面是 C++ 各个版本的主要变化和特性介绍:

1. C++ 1985: C++ 1.0

  • 最初版本:由贝尔实验室的 Bjarne Stroustrup 在 1980 年代初期开发。
  • 主要特点
    • 在 C 语言的基础上加入了面向对象编程(OOP)特性。
    • 支持类、继承、多态、封装等面向对象的基本特性。
    • 引入了函数和运算符重载。

C++ 1.0 是由 Bjarne Stroustrup 在贝尔实验室开发的第一版 C++ 编程语言。它是在 C 语言的基础上加入了面向对象编程(OOP)的特性,因此也被称为是“C with Classes”(C 带类)。C++ 1.0 并不是一个标准化的语言版本,而是一个实验性语言,它为后来的 C++ 标准奠定了基础。

主要特性:
  1. 类与对象:C++ 1.0 引入了面向对象编程的核心概念,最初的类和对象支持比较简单。

    • 类是 C++ 中的基本构造,用于封装数据和功能。
    • 对象是类的实例,表示实际的数据和行为。
  2. 函数和运算符重载:C++ 1.0 支持函数重载和运算符重载,使得程序员可以根据需要定义不同版本的函数或操作符。

  3. 基本继承:C++ 1.0 支持从一个类继承另一个类,使得可以构建更为复杂的类结构。

  4. 无标准库:当时的 C++ 语言没有像现代 C++ 那样的标准库。数据结构和算法通常依赖开发者自己编写。

示例代码:

C++ 1.0 版本的代码相对简单。以下是一个典型的 C++ 1.0 示例,演示了类的定义、对象创建、继承以及运算符重载。

#include <iostream>
using namespace std;// 定义一个类
class Box {
private:double length;   // 长度double breadth;  // 宽度double height;   // 高度public:// 构造函数Box(double l, double b, double h) {length = l;breadth = b;height = h;}// 计算体积的方法double volume() {return length * breadth * height;}// 运算符重载Box operator+(const Box& b) {// 返回一个新的 Box 对象,体积相加return Box(length + b.length, breadth + b.breadth, height + b.height);}
};// 主函数
int main() {// 创建对象Box box1(3.5, 1.2, 2.0);Box box2(1.0, 2.0, 3.0);// 计算并输出 box1 的体积cout << "Box1 Volume: " << box1.volume() << endl;// 运算符重载使用示例Box box3 = box1 + box2;cout << "Box3 Volume (box1 + box2): " << box3.volume() << endl;return 0;
}

代码讲解:

  • **类 Box**:定义了一个包含 lengthbreadth 和 height 的类,用于表示一个盒子,并且提供了一个计算体积的方法 volume()
  • 构造函数:用于初始化 Box 对象,设置它的长度、宽度和高度。
  • 运算符重载:使用 operator+ 重载运算符 +,使得两个 Box 对象相加时,返回一个新的 Box 对象,长度、宽度和高度分别相加。
  • 在 main() 中创建对象:通过构造函数创建了 box1 和 box2,并计算它们的体积。在计算 box3 的体积时,使用了重载的加法运算符。

C++ 1.0 的局限性:

  • 缺少模板:当时的 C++ 并不支持模板(泛型编程),模板编程是后来在 C++ 1990 和 1998 标准中引入的。
  • 没有标准库:没有现代 C++ 的 STL(标准模板库),因此没有常用的容器、算法等功能。
  • 继承的支持较为基础:C++ 1.0 支持继承,但还没有引入多态、虚函数等更高级的特性。

总结:

C++ 1.0 是 C++ 语言的初步版本,它为面向对象编程提供了基础设施,并通过类、对象、继承、重载等功能扩展了 C 语言的功能。虽然当时的 C++ 功能较为简单,但它为后续版本的语言特性打下了基础,并引领了 C++ 向更强大的方向发展。

2. C++ 1989: C++ 2.0

  • 增强功能
    • 多重继承:支持多个基类的继承。
    • 虚继承:解决多重继承中的“菱形继承”问题,确保继承层次中的基类只有一份副本。
    • 抽象类:引入了纯虚函数(抽象类)的概念,使得类能够定义接口。

C++ 2.0 是 C++ 语言的第二个重要版本,发布于 1989 年。C++ 2.0 在 C++ 1.0 的基础上进行了重要的扩展和改进,引入了多个新特性,特别是 多重继承 和 虚继承。这些新特性使得 C++ 的面向对象编程能力得到了显著增强。C++ 2.0 为后来的 C++ 语言标准奠定了许多重要基础。

主要特性:
  1. 多重继承:C++ 2.0 引入了多重继承的支持,使得一个类可以继承多个基类,从而可以组合多个类的功能。
  2. 虚继承:为了解决多重继承带来的“菱形继承”问题(即一个类通过多个继承路径继承同一个基类),C++ 2.0 引入了 虚继承 的概念。虚继承确保通过多个继承路径继承的同一个基类只有一份副本。
  3. 虚函数:继续扩展了对面向对象编程的支持,尤其是通过 虚函数 机制,使得 C++ 支持 运行时多态
  4. 更强的类型检查:C++ 2.0 对类型检查进行了增强,使得语言的类型系统更加严格和安全。

多重继承与虚继承

C++ 2.0 的最大变化之一就是支持 多重继承,并且引入了 虚继承 来解决多重继承可能引起的问题。在多重继承中,如果一个类继承自多个基类,并且这些基类有公共的祖先类,那么在派生类中会有重复的祖先类副本,这时就可能出现问题。虚继承解决了这一问题,通过确保只有一个祖先类副本,从而避免了数据冗余和潜在的错误。

示例代码:

以下是一个简单的示例,演示了 多重继承 和 虚继承 的概念。

#include <iostream>
using namespace std;// 基类A
class A {
public:A() { cout << "Class A constructor" << endl; }void showA() { cout << "Class A" << endl; }
};// 基类B
class B {
public:B() { cout << "Class B constructor" << endl; }void showB() { cout << "Class B" << endl; }
};// 基类C,虚继承A
class C : virtual public A {
public:C() { cout << "Class C constructor" << endl; }void showC() { cout << "Class C" << endl; }
};// 派生类D,虚继承A和B
class D : public C, public B {
public:D() { cout << "Class D constructor" << endl; }void showD() { cout << "Class D" << endl; }
};int main() {// 创建派生类对象DD d;d.showA(); // 来自基类Ad.showB(); // 来自基类Bd.showC(); // 来自基类Cd.showD(); // 来自派生类Dreturn 0;
}

代码讲解:

  • 类 A 和 BA 和 B 是两个基类,都有自己的构造函数和成员函数。A 有一个 showA() 函数,B 有一个 showB() 函数。
  • 类 CC 类继承了 A 类,并使用 virtual 关键字进行 虚继承。这样,在 C 的子类中,如果有多个继承自 A 的路径,它们会共享同一个 A 类副本,避免了重复数据。
  • 类 DD 类从 C 和 B 继承,并且通过虚继承机制共享了 A 类的副本。
  • 输出
    • 当 D 类的对象被创建时,首先调用 AB 和 C 的构造函数,再调用 D 的构造函数。
    • showA()showB() 和 showC() 分别调用了从基类继承的成员函数。

运行输出:

Class A constructor
Class B constructor
Class C constructor
Class D constructor
Class A
Class B
Class C
Class D

解释:

  • 虚继承C 类通过 virtual public A 虚继承了 A 类,保证了通过 D 类的继承关系,A 类只有一份副本。即使 D 类是通过 B 和 C 两个路径继承 AA 类也只会被构造一次。
  • 多重继承D 类通过多重继承继承了 B 和 C,因此 D 类拥有 B 和 C 类的功能。

C++ 2.0 的局限性:

  • 没有命名空间:C++ 2.0 并没有引入命名空间(namespace),因此容易出现命名冲突的问题。
  • 没有模板支持:模板编程(如函数模板和类模板)在 C++ 2.0 中还没有出现,这一特性是在 C++ 3.0 中引入的。
  • 继承体系较为简化:虽然支持多重继承和虚继承,但对继承体系的支持仍较为基础,随着 C++ 后续版本的发布,继承和多态的功能会得到更完善的支持。

总结:

C++ 2.0 通过引入 多重继承 和 虚继承 大大增强了 C++ 的面向对象能力,使得 C++ 成为一种更强大的编程语言。这些特性让 C++ 能够支持更复杂的类层次结构,解决了多重继承中的一些难题。虽然 C++ 2.0 语言仍然很基础,但它为 C++ 后续版本的更高级特性,如模板和更复杂的类型系统,奠定了基础。

3. C++ 1990: C++ 3.0

  • 功能增强
    • 模板:引入了模板(函数模板和类模板),开始支持泛型编程。
    • 标准库:初步支持了标准模板库(STL)的概念,虽然 STL 直到后来的版本才成为标准。

C++ 3.0 是 C++ 语言的第三个版本,发布于 1990 年。相比于前两个版本,C++ 3.0 在语言特性和功能上做出了重要的扩展,最为关键的就是引入了 模板 的支持,这是 C++ 语言向 泛型编程 过渡的重要一步。模板的引入使得 C++ 支持编写与类型无关的代码,从而使得编程变得更加灵活和强大。

主要特性:
  1. 模板(Templates)

    • 函数模板:允许定义可以接受不同类型参数的函数。
    • 类模板:允许定义可以接受不同类型参数的类。模板是 C++ 语言中泛型编程的基础。
  2. 增强的类型系统

    • 支持更复杂的类型定义和类型推导。
    • 改进了类和对象的类型推断机制。
  3. 基本的标准库(STL的雏形)

    • 尽管 C++ 3.0 本身并没有正式定义标准模板库(STL),但它开始支持类似 STL 的一些容器和算法概念,为未来 STL 的引入奠定了基础。
  4. 支持虚函数、运算符重载等特性

    • C++ 3.0 继续扩展了面向对象编程的支持,增强了对继承、多态、运算符重载等特性的支持。

模板的引入

C++ 3.0 的核心改进就是引入了模板机制,使得函数和类能够接受参数类型作为模板参数。这使得 C++ 能够支持泛型编程,从而能够编写类型安全且重用性更高的代码。

示例代码:模板示例

以下是一个简单的示例,展示了如何在 C++ 3.0 中使用 函数模板 和 类模板

#include <iostream>
using namespace std;// 函数模板:计算两个数字的最大值
template <typename T>
T getMax(T a, T b) {return (a > b) ? a : b;
}// 类模板:定义一个简单的容器类
template <typename T>
class Box {
private:T value;
public:Box(T v) : value(v) {}T getValue() { return value; }void setValue(T v) { value = v; }
};int main() {// 使用函数模板int x = 10, y = 20;cout << "Max of x and y: " << getMax(x, y) << endl;double a = 3.14, b = 2.71;cout << "Max of a and b: " << getMax(a, b) << endl;// 使用类模板Box<int> intBox(100);cout << "Box contains: " << intBox.getValue() << endl;intBox.setValue(200);cout << "Updated Box contains: " << intBox.getValue() << endl;Box<double> doubleBox(3.14159);cout << "Box contains: " << doubleBox.getValue() << endl;return 0;
}

代码讲解:

  • **函数模板 getMax**:

    • getMax 是一个函数模板,它接受两个类型为 T 的参数,返回它们中的最大值。
    • T 是一个类型参数,可以是任何数据类型(如 intdouble 等),当调用模板函数时,编译器会根据传入的参数类型推导出 T 的具体类型。
  • **类模板 Box**:

    • Box 是一个类模板,它有一个类型为 T 的成员变量 value
    • 构造函数接受一个 T 类型的参数来初始化 value,并提供了 getValue 和 setValue 方法来访问和修改 value

运行输出:

Max of x and y: 20
Max of a and b: 3.14
Box contains: 100
Updated Box contains: 200
Box contains: 3.14159

代码解释:

  • getMax 函数模板:在 main() 中,分别使用了 int 和 double 类型的参数来调用 getMax 函数模板。编译器根据传入的参数类型推导出 T 的类型。
  • Box 类模板Box<int> 和 Box<double> 分别是使用 int 和 double 类型的类模板实例化出来的对象。每个 Box 对象可以存储不同类型的数据。

模板的优势:

  • 代码重用:通过模板,函数和类可以支持多种不同的类型,而不需要为每个类型编写重复的代码。
  • 类型安全:模板在编译时进行类型检查,确保类型的正确性,避免了运行时的类型错误。

C++ 3.0 的局限性:

  • 模板特性较为基础:C++ 3.0 中的模板机制较为简单,没有现代 C++ 中复杂的模板特性,如模板特化、SFINAE(Substitution Failure Is Not An Error)等。
  • 标准库仍然不成熟:尽管模板提供了更多的灵活性,但标准库并没有像 C++11 和 C++14 中那样强大,STL 的概念才刚刚开始萌芽。

总结:

C++ 3.0 是 C++ 语言的一个重要版本,模板的引入是其最大的亮点,标志着 C++ 进入了泛型编程的时代。模板让 C++ 变得更加灵活,支持更加高效的代码重用和类型安全的操作。通过函数模板和类模板,C++ 可以在不同类型之间共享代码,从而极大地提高了开发效率和代码的可维护性。虽然 C++ 3.0 的模板机制相对简单,但它为后续的 C++ 标准化进程和更复杂的模板特性奠定了基础。

4. C++ 1998: C++98

  • C++ 标准化:C++98 是 C++ 的第一个正式标准版本,由 ISO/IEC 14882:1998 定义。
  • 主要特性
    • STL(标准模板库):引入了标准模板库,包括 vectorlistmapset 等容器,及算法(如排序、查找等)。map - C++ Reference    set - C++ Reference
    • 命名空间(namespace):为了避免名称冲突,引入了命名空间。
    • 异常处理:引入了 trycatchthrow 异常处理机制。
    • RTTI(运行时类型信息):引入了 typeid 和 dynamic_cast,允许运行时识别对象的类型。

C++98 是 C++ 语言的第一个国际标准,正式由 ISO(国际标准化组织)在 1998 年发布。C++98 语言标准继承了 C++ 3.0 的核心特性,并在此基础上进行了多个重要的改进和规范化。这个版本的 C++ 为标准库(STL)提供了规范,并开始支持更多的现代编程特性。

主要特性:
  1. 模板

    • C++98 中的模板特性得到了进一步的增强,支持函数模板和类模板,并且模板的使用变得更加广泛。模板参数可以是类、函数、指针等类型。
  2. 标准模板库(STL)

sort - C++ Reference

  1. 异常处理

    • C++98 提供了标准化的异常处理机制,使用 trycatchthrow 语句来处理运行时错误。
  2. 命名空间

    • C++98 引入了 命名空间namespace),用于避免名称冲突,尤其是在大型项目中。
  3. 虚函数与多态

    • C++98 继续强化了面向对象编程的支持,特别是对 虚函数 和 多态 的使用。
  4. const 和引用

    • C++98 对 const 关键字和引用进行了严格的规范,使得编程更加安全。
  5. 函数指针和类型转换

    • 提供了对 函数指针 和 类型转换(如 static_castdynamic_cast 等)的支持,增强了 C++ 的灵活性。
  6. 类成员的类型推导

    • C++98 引入了对类成员类型的推导,允许在某些情况下省略类型声明。
示例代码:C++98 的常见特性

以下是一个综合示例,展示了 C++98 中的几个核心特性,包括模板、标准库(STL)、命名空间和异常处理。

vector - C++ Reference

#include <iostream>
#include <vector>
#include <algorithm>
#include <stdexcept>namespace MyNamespace {// 模板函数:计算两个数的最大值template <typename T>T getMax(T a, T b) {return (a > b) ? a : b;}// 使用 STL 容器:vector 和算法void useSTL() {std::vector<int> vec = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5};std::sort(vec.begin(), vec.end());std::cout << "Sorted vector: ";for (int num : vec) {std::cout << num << " ";}std::cout << std::endl;}// 异常处理示例void testException() {try {throw std::out_of_range("Index out of range!");} catch (const std::exception& e) {std::cout << "Caught exception: " << e.what() << std::endl;}}
}int main() {// 使用命名空间using namespace MyNamespace;// 使用模板函数int x = 10, y = 20;std::cout << "Max of x and y: " << getMax(x, y) << std::endl;// 使用 STL 容器和算法useSTL();// 测试异常处理testException();return 0;
}

代码讲解:

  • **模板函数 getMax**:

    • 这是一个简单的模板函数,接受两个相同类型的参数,并返回它们中的最大值。typename T 表示这是一个模板函数,T 是占位符类型,可以在调用时由编译器自动推导出。
  • STL 容器和算法

    • 在 useSTL 函数中,使用了 std::vector 来存储整数数据,并使用 std::sort 算法对数据进行了排序。std::vector 是 C++98 标准库中的一个动态数组容器,std::sort 是一个算法函数,用于对容器中的元素进行排序。
  • 异常处理

    • testException 函数演示了 C++98 的异常处理机制。在这个函数中,抛出了一个 std::out_of_range 异常,并在 catch 块中捕获它,输出异常的描述信息。

运行输出:

Max of x and y: 20
Sorted vector: 1 1 2 3 3 4 5 5 5 6 9 
Caught exception: Index out of range!

代码解释:

  1. **模板 getMax**:通过模板,可以在运行时自动确定 T 的类型,支持不同的数据类型(如 intdouble 等)。在本例中,它比较了两个整数 x 和 y
  2. **STL 容器 std::vector 和 std::sort**:std::vector 是一个可以动态调整大小的容器,它存储一系列元素。std::sort 是一个通用算法,用来对容器中的元素进行排序。
  3. 异常处理:C++98 提供了标准的异常处理机制,允许在代码运行过程中抛出和捕获异常,避免程序因错误而崩溃。

C++98 的局限性:

  1. 没有 auto 关键字:C++98 中没有 auto 关键字,因此类型推导只能依靠显式的类型声明。
  2. **没有 nullptr**:C++98 中没有 nullptr,指针使用时可能会引发隐式的类型转换问题。
  3. 没有类型推导的 for 循环:C++98 中没有像 C++11 中那样的基于范围的 for 循环(for (auto& elem : container))。
  4. 模板元编程有限:虽然模板功能在 C++98 中已被引入,但对于模板元编程的支持相对有限,模板编程的复杂性和灵活性较低。

总结:

C++98 是 C++ 语言的第一个国际标准版本,它巩固并标准化了之前 C++3.0 中的许多特性,并加入了 模板 和 STL 等重要特性,使得 C++ 在实际开发中更加高效和灵活。通过模板,C++98 使得代码可以在不同的数据类型之间重用,同时标准库(STL)提供了高效的容器和算法支持,大大提高了开发效率。虽然 C++98 为后来的 C++ 标准奠定了基础,但它在某些领域(如模板编程和自动类型推导)仍存在局限。

5. C++ 2003: C++03

  • 修复和改进
    • 小的改进:C++03 主要是对 C++98 标准的一些修订和错误修正,没有引入重大新特性。
    • 支持一些新的编译器特性,如增强的模板支持、异常安全性等。

C++03 是 C++ 语言的一个小版本更新,它是对 C++98 的修正版本,主要用于解决一些语言上的不一致性和设计上的小问题。C++03 并未引入许多新的功能,而是对 C++98 标准中的一些细节进行了修正和澄清,确保语言的一致性和规范性。这个版本主要集中在语言规范的完善和一些编译器支持方面。

C++03 的发布并没有像 C++98 到 C++11 之间的版本那样进行革命性的更新,因此它在功能上与 C++98 并无太大差异。主要的更新包括对 模板特化SFINAE(Substitution Failure Is Not An Error)等方面的细节修正,确保了编译器能够更好地支持标准库。

主要特性和变化:

  1. 模板的修正和改进

    • C++03 对模板特化和模板元编程做了小的修正,使得编译器对模板的支持更加一致。
    • 改进了模板在某些边界情况中的行为,避免了 C++98 中一些不一致或令人困惑的部分。
  2. 标准库的修正

    • C++03 对标准库中的一些接口做了微调,解决了 C++98 标准库中的一些小问题。例如,修复了 std::vector 在某些情况下的行为不一致性,确保了 STL 中的算法与容器的更好兼容性。
  3. 修复了常见的编译器问题

    • C++03 对一些编译器的兼容性问题进行了修复,确保不同厂商的编译器之间有更好的兼容性。
  4. 去除了某些不再使用的特性

    • C++03 删除了一些在 C++98 中冗余或未被广泛使用的特性,从而使标准更加精简和一致。

C++03 与 C++98 的区别:

  • 细节修正:C++03 主要是针对 C++98 标准中存在的某些歧义性和编译器实现差异进行修正。它并没有加入新的语言特性,而是专注于优化语言和标准库的现有特性。
  • STL 和模板的完善:C++03 解决了模板和标准库的一些小问题,确保标准库在不同编译器下的行为一致。

示例代码:C++98 和 C++03 的差异

由于 C++03 与 C++98 的差异主要体现在语言的细节上,因此以下示例代码在 C++03 中的表现与 C++98 是相同的。我们展示一些在 C++98 和 C++03 中模板使用的常见问题,这些问题在 C++03 中得到了修正。

示例代码:模板特化修复和 SFINAE 改进
#include <iostream>
#include <type_traits>// 模板类的默认实现
template <typename T>
class Printer {
public:static void print(const T& value) {std::cout << value << std::endl;}
};// 特化:对于 const 类型的处理
template <typename T>
class Printer<const T> {
public:static void print(const T& value) {std::cout << "const value: " << value << std::endl;}
};// 使用 SFINAE 来选择函数
template <typename T>
typename std::enable_if<!std::is_integral<T>::value, void>::type
printType(const T& value) {std::cout << "Non-integer value: " << value << std::endl;
}template <typename T>
typename std::enable_if<std::is_integral<T>::value, void>::type
printType(const T& value) {std::cout << "Integer value: " << value << std::endl;
}int main() {Printer<int>::print(123);  // 默认模板Printer<const int>::print(456);  // 特化模板printType(123);  // 调用整数版本printType(3.14);  // 调用非整数版本return 0;
}

代码解释:

  1. 模板类 Printer 的特化

    • Printer 是一个模板类,在默认情况下,它的 print 函数打印任意类型的值。
    • 特化版本 Printer<const T> 对 const 类型的处理进行了特殊化,使其输出时带有 "const value: " 字样。此特化是在 C++03 中明确规定的,确保了特化行为的统一性。
  2. SFINAE(Substitution Failure Is Not An Error)

    • printType 函数使用了 SFINAE 来根据类型 T 的不同选择不同的版本。

    • 使用 std::enable_if 和 std::is_integral 来判断 T 是否为整数类型,并分别调用不同的函数。SFINAE 机制可以避免无效的模板实例化,确保了代码的类型安全。

    • 如果 T 是整数类型,printType(int) 会被调用;否则,printType(double) 会被调用。

运行输出:

123
const value: 456
Integer value: 123
Non-integer value: 3.14

C++03 与 C++98 的局限性:

  1. 没有新的语言特性:C++03 仅仅是 C++98 的修正版本,没有引入新的语言特性。开发者并未从中获得像 C++11、C++14、C++17 那样的重大进展。
  2. 标准库的改进有限:虽然 C++03 修复了一些标准库的问题,但与后来的 C++ 标准相比,它的功能仍显得较为简单。
  3. 没有现代化工具:如 autonullptr、范围 for 循环等特性都没有出现在 C++03 中,这使得它在一些现代编程需求面前显得有些过时。

总结:

C++03 是一个对 C++98 的修正版本,主要修复了一些语言规范中的小错误和不一致性,改进了模板、STL 和编译器的兼容性。它并没有引入新的语言特性,因此在实际使用中,C++98 和 C++03 的差异并不显著。C++03 主要对 C++98 的一些不明确之处进行了修正,为后续 C++ 标准的进化(如 C++11、C++14)奠定了基础。对于开发者来说,C++03 更多的是一种稳定性和兼容性更新,而不是一种功能性扩展。

6. C++ 2011: C++11

  • 现代 C++ 的起点:C++11 是 C++ 的一次重大更新,被广泛认为是 C++ 语言的“现代化”转折点。
  • 关键特性:
    • 自动类型推断(auto):使用 auto 关键字可以让编译器推断变量类型。
    • 智能指针:引入了 std::unique_ptrstd::shared_ptrstd::weak_ptr,用于自动管理内存,避免内存泄漏。
    • Lambda 表达式:允许定义匿名函数,可以在代码中更方便地使用函数对象。
    • 并发支持:引入了 <thread> 库,允许多线程编程。
    • **nullptr**:引入了 nullptr 关键字,替代 NULL,提高代码的类型安全。
    • 右值引用和移动语义:引入右值引用(&&)和 std::move,提高对象传递效率,减少不必要的拷贝。
    • 范围 for 循环:引入了简洁的范围 for 循环,简化容器遍历。
    • 类型别名(using):引入 using 关键字,简化类型别名定义。
    • 变长模板(Variadic Templates):支持可变参数模板,提高模板的灵活性。

C++11 是 C++ 语言的一个重大更新,正式于 2011 年发布。它引入了大量新的特性和改进,使 C++ 语言更现代化、更加高效和易于使用。C++11 标准的推出,极大地扩展了 C++ 的功能,使得 C++ 开发变得更加灵活、简洁,同时还提升了性能。

主要新特性:

  1. 自动类型推导(auto

    • auto 关键字允许编译器根据表达式的类型自动推导变量的类型,减少了类型声明的冗余,提高了代码可读性。
  2. 右值引用与移动语义(&& 和 std::move

    • 引入右值引用(&&)和 std::move,实现了 移动语义。通过移动资源而不是复制,显著提高了效率,尤其在需要大量数据传输的场合(如容器操作)。
  3. 范围 for 循环

    • 引入了范围 for 循环(range-based for loop),简化了容器元素的遍历,避免了传统迭代器的复杂性。
  4. Lambda 表达式

    • Lambda 表达式允许在函数内定义匿名函数,并且可以捕获外部变量,极大地增强了函数式编程的支持。
  5. **nullptr**:

    • nullptr 替代了 NULL,它是一个类型安全的空指针常量,消除了 NULL 的类型不匹配问题。
  6. **constexpr**:

    • constexpr 使得可以在编译时求值的常量表达式更加简洁,增强了编译期计算的能力。
  7. 并发编程:<thread> 库

    • C++11 引入了原生的线程支持,<thread> 库使得多线程编程变得更加容易和高效。
  8. 类型别名(using

    • using 关键字可以用来为类型定义别名,取代了传统的 typedef,语法更加简洁。
  9. 强类型枚举(enum class

    • 引入了强类型枚举 enum class,避免了传统枚举可能产生的隐式转换和命名冲突问题。
  10. **新标准库:std::chrono**:

    • C++11 引入了用于处理时间和日期的新标准库 std::chrono,使得处理时间变得更加直观和精确。

示例代码:C++11 特性

下面的代码示例展示了 C++11 的一些关键特性。

#include <iostream>
#include <vector>
#include <algorithm>
#include <thread>
#include <functional>// 1. 自动类型推导
void autoExample() {auto x = 10;  // 编译器自动推导类型为 intauto y = 3.14;  // 编译器自动推导类型为 doublestd::cout << "x: " << x << ", y: " << y << std::endl;
}// 2. 范围 for 循环
void rangeBasedFor() {std::vector<int> vec = {1, 2, 3, 4, 5};for (auto& num : vec) {  // 使用范围 for 遍历num *= 2;}std::cout << "Doubled values: ";for (const auto& num : vec) {std::cout << num << " ";}std::cout << std::endl;
}// 3. Lambda 表达式
void lambdaExample() {std::vector<int> vec = {1, 2, 3, 4, 5};int sum = 0;// 使用 lambda 表达式进行求和std::for_each(vec.begin(), vec.end(), [&sum](int num) { sum += num; });std::cout << "Sum of elements: " << sum << std::endl;
}// 4. 移动语义和右值引用
class MyClass {
public:MyClass() { std::cout << "Constructor\n"; }MyClass(const MyClass&) { std::cout << "Copy Constructor\n"; }MyClass(MyClass&&) { std::cout << "Move Constructor\n"; }MyClass& operator=(const MyClass&) { std::cout << "Copy Assignment\n"; return *this; }MyClass& operator=(MyClass&&) { std::cout << "Move Assignment\n"; return *this; }
};void moveExample() {MyClass a;MyClass b = std::move(a);  // 使用移动构造函数
}int main() {// 自动类型推导autoExample();// 范围 for 循环rangeBasedFor();// Lambda 表达式lambdaExample();// 移动语义moveExample();// 使用线程std::thread t([]{ std::cout << "Hello from a thread!\n"; });t.join();  // 等待线程执行完毕return 0;
}

代码解释:

  1. **自动类型推导 (auto)**:

    • 使用 auto 关键字,编译器会自动推导变量 x 和 y 的类型,简化了类型声明,特别是对于复杂类型(如迭代器和函数返回类型)时非常有用。
  2. 范围 for 循环

    • 使用 C++11 引入的范围 for 循环来遍历容器。这个语法简洁、直观,避免了显式的迭代器操作。
  3. Lambda 表达式

    • 使用 std::for_each 算法与 lambda 表达式结合,计算容器中所有元素的总和。lambda 表达式 [&sum](int num) { sum += num; } 捕获外部变量 sum 并对容器中的每个元素执行加法操作。
  4. 右值引用与移动语义

    • 在 moveExample 中,通过 std::move 实现了对象 a 的移动,将其资源转移给对象 b,触发了移动构造函数而不是拷贝构造函数。
  5. 线程支持

    • 使用 C++11 的 <thread> 库创建和启动一个线程,并且通过 join() 等待线程执行完成。std::thread 简化了多线程编程。

运行输出:

x: 10, y: 3.14
Doubled values: 2 4 6 8 10
Sum of elements: 15
Move Constructor
Hello from a thread!

C++11 的优势:

  • 现代化的语法和功能:C++11 引入的众多新特性大大提升了语言的灵活性和表达力,减少了冗余代码,使得 C++ 编程更加简洁、易读和高效。
  • 性能优化:通过右值引用和移动语义,C++11 使得许多数据传输和复制操作得以高效地优化,特别是在容器和大型对象的操作中,性能大幅提升。
  • 并发支持:C++11 将多线程支持纳入语言标准,使得并发编程变得更加容易和可靠,减少了对外部库的依赖。

C++11 的局限性:

  • 学习曲线:尽管 C++11 引入了许多现代化特性,但对一些开发者来说,掌握这些新特性可能需要一定的学习时间。
  • 编译器支持问题:尽管大部分现代编译器已经完全支持 C++11,但一些旧的编译器或开发环境可能存在兼容性问题。

总结:

C++11 是 C++ 语言的一次重大更新,带来了许多新的语言特性和库支持,使得 C++ 编程变得更加简洁、强大和高效。无论是在性能优化、现代语法的引入,还是在并发支持等方面,C++11 都大幅提升了语言的可用性和表达能力。

7. C++ 2014: C++14

  • 小幅增强:
    • constexpr 的改进:支持更复杂的编译时常量计算。
    • 二进制字面量:引入了支持二进制常量字面量。
    • auto 的增强:使得 auto 可以推导更加复杂的类型。
    • Lambda 表达式的改进:支持更强的捕获特性(如捕获 *this 引用)。

C++14 是 C++ 语言的一个相对较小的更新版本,于 2014 年发布。C++14 并没有像 C++11 那样引入大量的新特性,而是对 C++11 中的一些特性进行了修复、增强和小幅优化。它的目标是提高语言和标准库的稳定性,改进一些 C++11 的边界情况,增强编译器的支持,并提供一些性能上的提升。

主要新特性:

  1. 泛型 Lambda 表达式

    • C++14 扩展了 C++11 中的 Lambda 表达式,引入了泛型 Lambda,使得 Lambda 可以接受不同类型的参数而不需要显式地指定类型。
  2. 变量模板

    • C++14 引入了 变量模板,允许创建像模板函数一样的模板变量。之前只有函数和类可以是模板,但 C++14 使得变量也可以具有模板特性。
  3. Lambda 表达式的返回类型推导

    • 在 C++14 中,Lambda 表达式可以通过 auto 关键字自动推导返回类型。这避免了在 Lambda 表达式中手动指定返回类型的需要。
  4. **std::make_unique**:

    • 引入了 std::make_unique,作为 std::make_shared 的对称操作,它简化了对 std::unique_ptr 的创建,避免了不必要的 new 运算符。
  5. **decltype(auto)**:

    • 引入了 decltype(auto) 作为函数返回类型的推导方式,它可以推导出具有精确类型的返回值,支持返回引用类型的自动推导。
  6. 标准库改进

    • C++14 修复了 C++11 标准库中的一些问题,并改进了对各种常见编译器的支持。标准库中对线程、智能指针、算法等的支持变得更加稳定和高效。
  7. 二进制字面量

    • C++14 引入了二进制字面量(0b 或 0B)的支持,使得表示二进制数更加直观。
  8. **std::exchange**:

    • 新增了 std::exchange 函数,它可以简化交换操作,尤其是当你需要交换一个对象并返回其原值时。

示例代码:C++14 新特性

以下代码展示了 C++14 中的一些关键特性,包括泛型 Lambda、变量模板、decltype(auto)std::make_unique 等。

#include <iostream>
#include <vector>
#include <memory>
#include <algorithm>// 1. 泛型 Lambda 表达式
void genericLambda() {auto sum = [](auto a, auto b) { return a + b; };  // 泛型 Lambdastd::cout << "Sum of 3 and 4.5: " << sum(3, 4.5) << std::endl;
}// 2. 变量模板
template <typename T>
T pi = T(3.14159);void variableTemplate() {std::cout << "Pi as float: " << pi<float> << std::endl;std::cout << "Pi as double: " << pi<double> << std::endl;
}// 3. Lambda 表达式的返回类型推导
void lambdaReturnType() {auto multiply = [](auto a, auto b) { return a * b; };std::cout << "Multiply 4 and 5.5: " << multiply(4, 5.5) << std::endl;
}// 4. 使用 std::make_unique
void makeUnique() {auto ptr = std::make_unique<int[]>(5);  // 使用 make_unique 创建动态数组ptr[0] = 10;std::cout << "First element in unique_ptr array: " << ptr[0] << std::endl;
}// 5. 使用 decltype(auto) 推导返回类型
int&& returnRvalue() {int x = 5;return std::move(x);  // 返回右值引用
}void decltypeAuto() {decltype(auto) result = returnRvalue();std::cout << "Rvalue returned: " << result << std::endl;
}// 6. 使用 std::exchange
int increment(int& x) {return std::exchange(x, x + 1);  // 将 x 的当前值赋给函数并更新 x
}void exchangeExample() {int value = 10;int oldValue = increment(value);std::cout << "Old value: " << oldValue << ", New value: " << value << std::endl;
}int main() {// 泛型 LambdagenericLambda();// 变量模板variableTemplate();// Lambda 返回类型lambdaReturnType();// 使用 make_uniquemakeUnique();// 使用 decltype(auto)decltypeAuto();// 使用 std::exchangeexchangeExample();return 0;
}

代码解释:

  1. 泛型 Lambda 表达式

    • 通过 auto 来声明 Lambda 表达式的参数类型,使得 Lambda 可以接受任意类型的参数。这使得 Lambda 表达式更加灵活,可以应用于多种不同的类型。
  2. 变量模板

    • pi 是一个模板变量,它接受一个类型参数 T,并为每个类型提供不同的常量值。在 variableTemplate() 中,演示了如何使用模板变量来获取 pi 的不同类型值。
  3. Lambda 返回类型推导

    • 使用 auto 关键字,Lambda 表达式会自动推导返回类型。在 lambdaReturnType() 中,返回类型是乘积结果的类型,auto 会自动推导出其正确类型。
  4. **std::make_unique**:

    • std::make_unique 用于创建 std::unique_ptr,这是一个智能指针,用于管理动态分配的内存。std::make_unique 是 C++14 引入的,它比直接使用 new 更加安全和方便。
  5. **decltype(auto)**:

    • decltype(auto) 用于推导函数的返回类型,并且支持返回值是引用的情况。在 decltypeAuto() 中,returnRvalue() 返回一个右值引用,通过 decltype(auto) 可以正确地推导出返回类型。
  6. **std::exchange**:

    • std::exchange 是 C++14 引入的一个小工具,它用于交换一个变量的值并返回旧值。在 exchangeExample() 中,std::exchange 用于交换 value 的值并返回交换前的值。

运行输出:

Sum of 3 and 4.5: 7.5
Pi as float: 3.14159
Pi as double: 3.14159
Multiply 4 and 5.5: 22
First element in unique_ptr array: 10
Rvalue returned: 5
Old value: 10, New value: 11

C++14 的优势:

  • 增强的类型推导:通过 autodecltype(auto)、泛型 Lambda 表达式等新特性,C++14 提供了更加灵活和精简的编程体验。
  • 更强大的 Lambda 表达式:C++14 使得 Lambda 表达式支持更复杂的类型推导和捕获方式,提升了函数式编程的能力。
  • 内存管理优化std::make_unique 提高了内存管理的安全性和效率,避免了直接使用 new 时可能出现的资源泄漏问题。
  • 简化的交换操作std::exchange 使得交换操作更加简洁,尤其是在需要交换并返回原值的场景中。

C++14 的局限性:

  • 更新较小:相比 C++11,C++14 的新特性较少,更多的是对 C++11 特性的增强和补充。因此,C++14 的使用场景更多是在已有代码的优化和小修小补上。
  • 编译器支持:尽管大部分现代编译器支持 C++14,但早期的编译器可能对一些新特性的支持不完全,开发者在使用这些特性时需要确认编译器的兼容性。

总结:

C++14 是 C++ 语言的一个小版本更新,主要通过增强和扩展 C++11 中的特性来提升语言的灵活性、可用性和安全性。它引入了泛型 Lambda、变量模板、std::make_unique 等重要特性,并修复了 C++11 中的一些边界问题。C++14 对于已经使用 C++11 的开发者来说是一个重要的改进,但它的变化相对较小,不会像 C++11 那样对整个语言体系造成颠覆性的影响。

8. C++ 2017: C++17

  • 重要更新:
    • 结构化绑定声明:允许通过 auto [x, y] = pair 等语法,直接解构元组或结构体。
    • **std::filesystem**:引入文件系统库,提供跨平台的文件系统操作接口。
    • if 和 switch 初始化:允许在 if 或 switch 语句中直接初始化变量。
    • 并行算法:STL 中的算法库支持并行执行,如并行排序。
    • **std::optional**:提供了一个容器,可以包含一个值或为空,用于避免空指针的使用。
    • **std::variant**:实现了类似于联合体的类型,但比 C 的 union 更安全和灵活。
    • **改进的 std::any**:增强了类型安全的通用容器,允许存储任意类型。

C++17(也被称为C++ 2017)是C++编程语言的一个重要版本,它在C++11和C++14的基础上进行了许多改进,增强了语言特性、库功能以及编译器支持。C++17的主要亮点包括:

1. 结构化绑定声明 (Structured Bindings)

C++17 引入了结构化绑定,允许你将一个结构或元组拆分为多个变量,从而让代码更加简洁易读。

示例:
#include <tuple>
#include <iostream>std::tuple<int, double, std::string> getData() {return {1, 3.14, "Hello, C++17!"};
}int main() {auto [x, y, z] = getData();  // 结构化绑定std::cout << x << ", " << y << ", " << z << std::endl;return 0;
}

输出:

1, 3.14, Hello, C++17!

2. if/else语句中的初始化语句 (If/else with initialization)

C++17允许在ifelse语句中进行变量初始化,避免了冗余的变量声明。

示例:
#include <iostream>int main() {if (int x = 10; x > 5) {std::cout << "x is greater than 5" << std::endl;} else {std::cout << "x is not greater than 5" << std::endl;}return 0;
}

输出:

x is greater than 5

注意:x只在ifelse的作用域内有效。

3. std::optional

std::optional 是一个模板类,用来表示一个可能为空的值。它可以用来避免使用空指针或特殊值来表示无效数据。

示例:
#include <iostream>
#include <optional>std::optional<int> findValue(bool found) {if (found) {return 42;} else {return std::nullopt;  // 返回空值}
}int main() {auto value = findValue(true);if (value) {std::cout << "Found value: " << *value << std::endl;} else {std::cout << "Value not found" << std::endl;}return 0;
}

输出:

Found value: 42

4. std::string_view

std::string_view是一个轻量级的字符串视图,避免了复制字符串数据,提供了对字符串的只读访问。

示例:
#include <iostream>
#include <string_view>void printString(std::string_view str) {std::cout << str << std::endl;
}int main() {std::string str = "Hello, C++17!";printString(str);  // 不会复制数据return 0;
}

输出:

Hello, C++17!

5. std::filesystem

C++17加入了对文件系统操作的标准库支持,std::filesystem使得处理文件和目录变得更加方便。

示例:

<iostream> - C++ Reference

#include <iostream>
#include <filesystem>namespace fs = std::filesystem;int main() {fs::path p = "example.txt";if (fs::exists(p)) {std::cout << p << " exists!" << std::endl;} else {std::cout << p << " does not exist." << std::endl;}return 0;
}

输出:

example.txt does not exist.

6. 并行算法 (Parallel Algorithms)

C++17添加了对并行执行算法的支持,例如使用 std::for_each 和其他标准算法的并行执行。

示例:
#include <iostream>
#include <vector>
#include <algorithm>
#include <execution>int main() {std::vector<int> data = {1, 2, 3, 4, 5, 6, 7, 8, 9};std::for_each(std::execution::par, data.begin(), data.end(), [](int& x) {x *= 2;});for (int x : data) {std::cout << x << " ";}return 0;
}

输出:

2 4 6 8 10 12 14 16 18 

(注意:并行执行可能因环境不同而产生不同的输出顺序)

7. 内联变量 (Inline Variables)

C++17引入了内联变量,解决了头文件中静态变量带来的链接问题。

示例:
#include <iostream>inline int x = 42;  // 内联变量int main() {std::cout << x << std::endl;return 0;
}

8. 改进的constexpr

C++17扩展了constexpr的功能,允许在编译时执行更多的操作,比如动态分配内存和使用if语句。

示例:
#include <iostream>constexpr int factorial(int n) {return (n == 0) ? 1 : n * factorial(n - 1);
}int main() {std::cout << "Factorial of 5: " << factorial(5) << std::endl;return 0;
}

输出:

Factorial of 5: 120

总结

C++17引入了许多新特性,极大提高了语言的表达力和编程效率,尤其是在简化代码、提高性能和增加灵活性方面。对于现代C++开发者来说,熟练掌握这些特性将大大提升开发体验和代码质量。

9. C++ 2020: C++20

  • 重大的新特性:
    • 模块(Modules):引入了模块化的支持,替代传统的头文件和源文件方式,减少编译时间。
    • 协程(Coroutines):支持异步编程,简化了异步函数的编写。
    • 概念(Concepts):引入了模板约束,使得模板编程更加灵活和易于理解。
    • 范围(Ranges):增强了容器操作的灵活性和简洁性,提供了更强大的算法支持。
    • **std::format**:提供了类似 Python 中的格式化字符串功能,简化了输出。
    • **consteval 和 constinit**:新关键字,用于常量表达式和常量初始化的严格控制。
    • **改进的 constexpr**:支持更多的编译时功能,包括动态内存分配。

C++20 是 C++ 标准的一个重要更新,它在语言特性、库功能、并发支持等方面进行了大量的扩展和增强。C++20 对语言进行了重要的现代化,使得 C++ 更加高效、简洁、易用。以下是 C++20 中的一些主要特性及其代码示例:

1. 概念 (Concepts)

概念是 C++20 的一项新特性,用来约束模板类型。它允许我们更精确地控制模板参数类型,提供编译时检查和更好的错误信息。

示例:
#include <iostream>
#include <concepts>template <typename T>
concept Incrementable = requires(T a) { ++a; a++; };template <Incrementable T>
T increment(T x) {return ++x;
}int main() {int a = 5;std::cout << increment(a) << std::endl;  // 正常工作// std::string s = "Hello";// std::cout << increment(s) << std::endl; // 编译错误,因为 std::string 不符合 Incrementable 概念return 0;
}

输出:

6

2. 范围 (Ranges)

C++20 引入了 std::ranges,为标准库中的容器和算法提供了更加一致和方便的操作方法,支持通过管道操作符(|)组合算法。

示例:
#include <iostream>
#include <vector>
#include <ranges>int main() {std::vector<int> nums = {1, 2, 3, 4, 5};// 使用管道操作符对容器进行操作auto result = nums | std::views::transform([](int x) { return x * 2; })| std::views::filter([](int x) { return x > 5; });for (int val : result) {std::cout << val << " ";}return 0;
}

输出:

6 8 10

3. 协程 (Coroutines)

C++20 引入了协程支持,使得编写异步代码更加简洁。协程允许暂停和恢复函数的执行,适用于处理 I/O 操作或其他需要异步操作的场景。

示例:
#include <iostream>
#include <coroutine>struct Task {struct promise_type;using handle_type = std::coroutine_handle<promise_type>;struct promise_type {Task get_return_object() { return Task{handle_type::from_promise(*this)}; }std::suspend_always initial_suspend() { return {}; }std::suspend_always final_suspend() noexcept { return {}; }void unhandled_exception() { std::exit(1); }void return_void() {}};handle_type coro;Task(handle_type h) : coro(h) {}~Task() { coro.destroy(); }void resume() { coro.resume(); }
};Task simpleCoroutine() {std::cout << "Start of coroutine\n";co_await std::suspend_always{};std::cout << "End of coroutine\n";
}int main() {auto coro = simpleCoroutine();coro.resume();  // 启动协程coro.resume();  // 恢复协程return 0;
}

输出:

Start of coroutine
End of coroutine

4. 三向比较 (Spaceship Operator <=>)

C++20 引入了“太空船操作符” (<=>),也叫做三向比较操作符,它提供了一种简化的方式来执行比较操作,如 <<===>>=

示例:
#include <iostream>struct Point {int x, y;auto operator<=>(const Point&) const = default;  // 默认生成比较操作符
};int main() {Point p1 = {1, 2}, p2 = {2, 3};if (p1 < p2) {std::cout << "p1 is less than p2\n";}return 0;
}

输出:

p1 is less than p2

5. 模块 (Modules)

C++20 引入了模块的概念,这是对头文件的替代。模块可以提高编译速度,避免头文件带来的重复处理和依赖问题。模块支持 import 语句来替代传统的 #include

示例:

假设我们有一个模块 math

// math.cppm - 模块定义文件
export module math;
export int add(int a, int b) { return a + b; }

然后在主程序中导入该模块:

// main.cpp
import math;int main() {int result = add(3, 4);std::cout << result << std::endl;  // 输出 7return 0;
}

注意:模块在许多编译器中仍处于实验阶段,需要启用特定的编译器选项。

6. 范围循环 (Range-based for loop with initializer)

C++20 增强了范围 for 循环,允许在循环中初始化变量。

示例:
#include <iostream>
#include <vector>int main() {std::vector<int> nums = {1, 2, 3, 4};for (auto&& [index, value] : nums) {  // 使用结构化绑定std::cout << "Value: " << value << std::endl;}return 0;
}

输出:

Value: 1
Value: 2
Value: 3
Value: 4

7. std::span

std::span 是 C++20 新增的一个轻量级的视图容器,它可以用来表示一个数组的连续区间。它与传统的指针数组相比,更加安全,并支持对数组进行边界检查。

示例:
#include <iostream>
#include <span>void printSpan(std::span<int> sp) {for (auto val : sp) {std::cout << val << " ";}
}int main() {int arr[] = {1, 2, 3, 4, 5};printSpan(arr);  // 使用 std::span 传递数组return 0;
}

输出:

1 2 3 4 5 

8. consteval 和 constinit

C++20 引入了 consteval 和 constinit 关键字:

  • consteval 用于指定一个函数必须在编译时求值。
  • constinit 用于确保某个变量在初始化时是常量。
示例:
#include <iostream>consteval int square(int n) { return n * n; }int main() {constexpr int result = square(5);  // 在编译时计算std::cout << result << std::endl;  // 输出 25return 0;
}

输出:

25

总结

C++20 引入了许多强大的新特性,极大增强了 C++ 的表达能力和编程效率。它使得编写更现代、更安全和更高效的 C++ 代码变得更加容易。例如,概念和协程提高了代码的可读性和可维护性,而模块的引入可以显著提高编译性能。掌握 C++20 的特性将有助于编写更清晰、强大和高效的 C++ 代码。

10. C++ 2023: C++23

  • 新特性和小幅增强:
    • **扩展的 std::ranges**:提供更多的支持与增强,使得 C++ 的标准库更具表达力和功能。
      • 改进的协程支持:协程功能得到进一步加强,增加了更多的灵活性和优化。
    • 更好的标准化和规范:提高了 C++ 语言和标准库的易用性和性能。

C++23(正式名称为 C++23)是C++语言的最新标准,作为C++20和C++17之后的下一代标准,C++23在语言特性、库功能和编译器优化等方面引入了一些重要的改进。以下是C++23中的一些新特性和代码示例。

1. 改进的常量表达式(constexpr

C++23扩展了constexpr的功能,允许更多复杂的功能在编译时执行。例如,C++23允许在constexpr函数中使用try-catch语句,这在之前的标准中是无法实现的。

示例:
constexpr int safe_divide(int a, int b) {if (b == 0) throw std::invalid_argument("Division by zero");return a / b;
}int main() {constexpr int result = safe_divide(10, 2);  // 编译时执行return 0;
}

2. std::expected

C++23引入了std::expected,它是一个可以用来表示函数调用结果的类型,类似于std::optional,但是它包含了错误信息。这个特性非常适合替代try-catch块来进行错误处理,尤其是在函数返回时希望包含更多的错误信息时。

示例:
#include <expected>
#include <iostream>std::expected<int, std::string> divide(int a, int b) {if (b == 0) {return std::unexpected("Division by zero");}return a / b;
}int main() {auto result = divide(10, 0);if (result) {std::cout << "Result: " << *result << std::endl;} else {std::cout << "Error: " << result.error() << std::endl;}return 0;
}

3. 范围(Ranges)库增强

C++20引入了范围(Ranges)库,C++23在此基础上进行了增强。新增了更丰富的算法和视图,使得在进行集合操作时,代码更加简洁且易于理解。

示例:
#include <ranges>
#include <vector>
#include <iostream>int main() {std::vector<int> v = {1, 2, 3, 4, 5};// 使用ranges库处理集合auto result = v | std::views::transform([](int n) { return n * n; })| std::views::filter([](int n) { return n > 10; });for (int i : result) {std::cout << i << " ";}return 0;
}

4. std::format 改进

C++20引入了 std::format 来格式化字符串,C++23对其进行了进一步改进。新增了更多的格式化选项,以及对各种类型的支持。

示例:
#include <format>
#include <iostream>int main() {int age = 25;std::string name = "Alice";std::string formatted = std::format("Name: {}, Age: {}", name, age);std::cout << formatted << std::endl;return 0;
}

5. explicit 改进

C++23扩展了explicit关键字,可以用于更加灵活的构造函数,使其适应更复杂的类型转换需求。

示例:
struct A {explicit A(int x) {}  // 显式构造函数
};struct B {explicit B(A a) {}  // 显式构造函数
};int main() {A a(1);B b(a);  // 需要显示构造A对象的参数return 0;
}

6. std::span 支持的改进

std::span 是C++20中引入的用于表示数组片段的类,C++23对其进行了扩展,支持了更多的功能。

示例:
#include <span>
#include <iostream>void print_span(std::span<int> s) {for (auto elem : s) {std::cout << elem << " ";}
}int main() {int arr[] = {1, 2, 3, 4, 5};std::span<int> sp(arr, 3);  // 只传递数组的前3个元素print_span(sp);return 0;
}

7. 新的属性([[likely]] 和 [[unlikely]]

C++23引入了 [[likely]] 和 [[unlikely]] 属性,用于给编译器提供分支预测的提示,帮助优化代码。

示例:
#include <iostream>int main() {bool condition = true;if ([[likely]] condition) {std::cout << "Condition is likely true" << std::endl;} else {std::cout << "Condition is unlikely true" << std::endl;}return 0;
}

总结

C++23增强了语言的表达能力和效率,提供了更多的编程便利性,尤其在常量表达式、错误处理、范围操作、字符串格式化和编译时优化方面有显著的提升。这些特性使得C++更加现代化,代码更加简洁易懂,同时也带来了更高效的执行性能。

这些新特性和API增强为开发者提供了更加灵活和强大的工具,可以让代码更加高效、易维护并且更具可读性。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/71339.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 21. 合并两个有序链表(Python)

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 输入&#xff1a;l1 [1,2,4], l2 [1,3,4] 输出&#xff1a;[1,1,2,3,4,4] 示例 2&#xff1a; 输入&#xff1a;l1 [], l2 [] 输出&#xff1a;[] 示例 3&#xff1a; 输…

FPGA 配置原理

用户编程控制的FPGA 是通过加载比特位流配置内部的存储单元实现的。该存储单元就是所谓的配置单元&#xff0c;它必须在器件上电后进行配置&#xff0c;从而设置查找表&#xff08;LUT&#xff09;的属性、连线方式、IOB 电压标准和其它的用户设计。 1.配置帧 以Xilinx 公司的…

测试人员如何更好的跟踪BUG

软件测试中BUG跟踪是确保软件质量的关键环节。测试人员不仅需要发现BUG&#xff0c;还需有效管理其状态&#xff0c;从报告到修复验证的全过程。如何更好地跟踪BUG&#xff0c;成为测试人员提升效率的重要课题。本文将详细探讨测试人员可以采用的策略&#xff0c;包括使用工具、…

lamp平台介绍

一、lamp介绍 网站&#xff1a; 静态 动态 php语言 .php 作用&#xff1a;运行php语言编写动态网站应用 lamp Linux Apache MySQL PHP PHP是作为httpd的一个功能模块存在的 二、部署lamp平台 1、测试httpd是否可正常返回PHP的响应 2、测试PHP代码是否可正常连接数据…

2025年渗透测试面试题总结-字某跳动-渗透测试实习生(题目+回答)

网络安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 字某跳动-渗透测试实习生 渗透流程信息收集如何处理子域名爆破中的泛解析问题绕过CDN寻找真实IPPHPINFO页面关注…

Spring Boot 自动装配深度解析与实践指南

目录 引言&#xff1a;自动装配如何重塑Java应用开发&#xff1f; 一、自动装配核心机制 1.1 自动装配三大要素 1.2 自动装配流程 二、自定义自动配置实现 2.1 创建自动配置类 2.2 配置属性绑定 2.3 注册自动配置 三、条件注解深度应用 3.1 常用条件注解对比 3.2 自定…

《算法笔记》9.6小节 数据结构专题(2)并查集 问题 C: How Many Tables

题目描述 Today is Ignatius birthday. He invites a lot of friends. Now its dinner time. Ignatius wants to know how many tables he needs at least. You have to notice that not all the friends know each other, and all the friends do not want to stay with stra…

CPU、SOC、MPU、MCU--详细分析四者的区别

一、CPU 与SOC的区别 1.CPU 对于电脑&#xff0c;我们经常提到&#xff0c;处理器&#xff0c;内存&#xff0c;显卡&#xff0c;硬盘四大部分可以组成一个基本的电脑。其中的处理器——Central Processing Unit&#xff08;中央处理器&#xff09;。CPU是一台计算机的运算核…

Linux常用指令学习笔记

文章目录 前言一、文件和目录操作指令1. 文件操作2. 目录操作 二、文件权限管理三、网络相关指令四、系统管理指令五、文本编辑器基本操作 六、压缩和解压指令七、总结 前言 在当今的IT领域&#xff0c;Linux系统因其开源、稳定、安全等特性&#xff0c;广泛应用于服务器、个人…

android studio通过 jni 调用第三方非标准 so库

调用第三方的so方法&#xff0c;但这个so内的方法不是标准的jni方法。这就需要我们自己写jni然后链接到第三方so库&#xff0c;通过jni调用so库中的方法。 1.简述&#xff1a; 要先有第三方的so库.so文件和编译库对应的.h头文件 我们自己用 c/c 创建一个标准的so 库,比如 my…

Spring(三)容器-注入

一 自动注入Autowire 代码实现&#xff1a; package org.example.spring01.service;import org.springframework.stereotype.Service;Service public class UserService {}package org.example.spring01.controller;import lombok.Data; import lombok.ToString; import org.…

mac上最好的Python开发环境之Anaconda+Pycharm

为了运行修改 label-studio项目源码&#xff0c;又不想在windows上运行&#xff0c;便在mac上开始安装&#xff0c;开始使用poetry安装&#xff0c;各种报错&#xff0c;不是zip包解压不了&#xff0c;就是numpy编译报错&#xff0c;pipy.org访问出错。最后使用anaconda成功启动…

IDEA 接入 Deepseek

在本篇文章中&#xff0c;我们将详细介绍如何在 JetBrains IDEA 中使用 Continue 插件接入 DeepSeek&#xff0c;让你的 AI 编程助手更智能&#xff0c;提高开发效率。 一、前置准备 在开始之前&#xff0c;请确保你已经具备以下条件&#xff1a; 安装了 JetBrains IDEA&…

前缀和矩阵

前缀和矩阵&#xff08;Prefix Sum Matrix&#xff09;是一种预处理技术&#xff0c;用于快速计算二维矩阵中任意子矩阵的元素和。其核心思想是通过提前计算并存储每个位置左上角所有元素的和&#xff0c;将子矩阵和的查询时间从暴力计算的 (O(mn)) 优化到 (O(1))。以下是构建前…

系统架构评估中的重要概念

(1)敏感点(Sensitivity Point) 和权衡点 (Tradeoff Point)。敏感点和权衡点是关键的架构 决策。敏感点是一个或多个构件(和/或构件之间的关系)的特性。研究敏感点可使设计人员 或分析员明确在搞清楚如何实现质量目标时应注意什么。权衡点是影响多个质量属性的特性&#xff0c; …

SSL证书和HTTPS:全面解析它们的功能与重要性

每当我们在互联网上输入个人信息、进行在线交易时&#xff0c;背后是否有一个安全的保障&#xff1f;这时&#xff0c;SSL证书和HTTPS便扮演了至关重要的角色。本文将全面分析SSL证书和HTTPS的含义、功能、重要性以及它们在网络安全中的作用。 一、SSL证书的定义与基本概念 S…

基于微信小程序的停车场管理系统的设计与实现

第1章 绪论 1.1 课题背景 随着移动互联形式的不断发展&#xff0c;各行各业都在摸索移动互联对本行业的改变&#xff0c;不断的尝试开发出适合于本行业或者本公司的APP。但是这样一来用户的手机上就需要安装各种软件&#xff0c;但是APP作为一个只为某个公司服务的一个软件&a…

宝塔找不到php扩展swoole,服务器编译安装

1. 在php7.4中安装swoole&#xff0c;但找不到这个扩展安装 2. 服务器下载源码解压安装 http://pecl.php.net/package/swoole 下载4.8.0版本 解压到/www/server/php/74/下 3. 发现报错问题&#xff1b; 更新一下依赖 yum update yum -y install gcc gcc-c autoconf libjpe…

大数据测试总结

总结测试要点&#xff1a; 参考产品文档&#xff0c;技术文档梳理以下内容 需求来源 业务方应用场景 数据源&#xff0c;数据格转&#xff0c;数据产出&#xff0c;数据呈现方式&#xff08;数据消亡史&#xff09;&#xff0c;数据量级&#xff08;增量&#xff0c;全量&am…

React封装通用Table组件,支持搜索(多条件)、筛选、自动序号、数据量统计等功能。未采用二次封装调整灵活,包含使用文档

封装通用组件 一、封装思想二、react代码三、css代码四、实现效果五、使用文档 BasicTableModal 表格模态框组件1.组件简介2.功能特点3.使用方法基础用法宽度控制示例带筛选功能搜索功能示例自定义单元格渲染 4.API 说明PropsColumn 配置项Filter 配置项 5.注意事项 一、封装思…