当前位置:   article > 正文

C++简介_c++的特点

c++的特点

C++简介

C++是一种高级编程语言,它是对C语言的扩展和增强。C++由Bjarne Stroustrup于1980年发明,主要用于系统级编程、游戏开发、嵌入式系统等领域。

C++具有许多特性,其中最重要的是面向对象编程(OOP)。面向对象编程使得软件开发更加模块化、可重用和易于理解。C++还支持其他编程范式,如泛型编程、函数式编程等。

C++具有以下特点:

  1. 高效性:C++编译生成的机器码效率高,可以直接与硬件进行交互,可以在性能要求较高的应用中使用。

  2. 跨平台性:C++代码可以在不同的操作系统上进行编译和运行,例如Windows、Linux和Mac OS等。

  3. 强大的标准库:C++标准库提供了丰富的功能,涵盖了各种数据结构、算法、输入输出等。

  4. 内存管理:C++提供了手动内存管理的能力,程序员可以自己管理内存分配和释放,但也容易导致内存泄漏和悬挂指针等问题。

  5. 多范式支持:除了面向对象编程外,C++还支持泛型编程(通过模板实现)和函数式编程(通过Lambda表达式和函数对象实现)。

C++广泛应用于各种领域,特别是需要高性能和可控制性的应用,如游戏开发、图形界面开发、嵌入式系统、金融系统、科学计算等。同时,C++也是其他一些流行编程语言的基础,如Java、Python等,很多开源项目也是用C++开发的。

C++版本

C++有多个版本,每个版本都引入了一些新的功能和改进。以下是一些常见的C++版本:

  1. C++98/C++03:这是最早的C++标准版本,也被称为C++98或C++03。它包含了基本的面向对象编程特性,如类、继承、多态等,以及一些库,如STL(标准模板库)。

  2. C++11:于2011年发布的C++标准,引入了许多新特性,如自动类型推导(auto关键字)、Lambda表达式、右值引用、智能指针、范围for循环等。此外,C++11还增加了一些标准库组件,如std::thread(多线程支持)、std::regex(正则表达式支持)等。

  3. C++14:在C++11的基础上进行了一些小的改进和修复,于2014年发布。C++14没有引入太多的新特性,主要是对语法进行了改进和简化。

  4. C++17:在2017年发布的C++标准,引入了一些重要的新特性,如结构化绑定、if constexpr、折叠表达式、并行算法等。C++17对并发编程、文件系统操作和元编程等方面进行了改进。

  5. C++20:于2020年发布的C++标准,包含了许多新特性,如概念(Concepts)、三向比较运算符、协程(Coroutines)、范围概论(Ranges)、异步操作等。C++20进一步改进了语言的表达能力和库的功能。

请注意,以上只是列举了一些常见的C++版本,随着时间的推移,C++标准会继续演变和更新,引入更多的功能和改进。开发人员可以根据需要选择适合自己项目的C++版本。

C++11

以下是对C++11引入的主要新特性的进一步详细介绍:

  1. 自动类型推导(auto):使用auto关键字声明变量时,编译器会根据右侧的初始化表达式推导出变量的类型。这样可以简化代码,并且在使用模板时特别有用,可以避免手动指定模板参数类型。

  2. Lambda表达式:Lambda表达式允许我们在需要一个函数对象的地方定义一个匿名函数。它的语法形式为[]() { /* 函数体 */ },其中[]是捕获列表,()是参数列表,{}是函数体。Lambda表达式可以方便地在现场创建函数对象,并且可以捕获外部变量,使得代码更加简洁和灵活。

  3. 右值引用(Rvalue references):右值引用允许我们将右值(临时对象、表达式结果等)绑定到一个可修改的引用上。通过移动语义,我们可以在不进行深拷贝的情况下转移对象的资源,提高性能。另外,右值引用还开启了完美转发的可能性,可以实现更灵活的函数参数传递。

  4. 智能指针(Smart Pointers):智能指针是C++11引入的三种指针类,包括std::shared_ptr、std::unique_ptr和std::weak_ptr。它们提供了自动内存管理,可以在对象不再需要时自动释放内存,避免了手动调用delete操作和内存泄漏的风险。其中,std::shared_ptr使用引用计数来管理对象的生命周期,std::unique_ptr拥有对象的独占权,而std::weak_ptr则用于解决循环引用问题。

  5. 范围for循环(Range-based for loop):范围for循环是一种更加简洁的遍历容器元素的语法形式。它使用范围表达式来遍历容器中的每个元素,而无需使用迭代器或者手动控制循环变量。

  6. 静态断言(static_assert):静态断言是在编译时检查某个条件是否为真的机制。如果条件不满足,则会导致编译错误,并显示用户指定的错误消息。

  7. 空指针常量(nullptr):C++11引入了一个新的空指针常量nullptr,用于表示空指针,取代了之前使用的NULL宏。nullptr具有明确的类型,并且支持与其他指针类型进行比较。

  8. 并发编程支持:C++11引入了一些基本的并发编程支持,如std::thread和std::mutex等。这些标准库组件使得多线程编程更加方便和安全,可以轻松创建线程、实现互斥保护和同步操作。

  9. 泛型编程增强:C++11引入了一些增强的泛型编程特性,包括模板别名(template alias)、可变参数模板(variadic templates)、类型转发(perfect forwarding)等。这些特性使得泛型代码更加灵活和易用,可以更好地支持模板元编程和泛型库开发。

  10. 移动语义(Move semantics):移动语义是通过移动构造函数和移动赋值运算符来实现的,在对象移动时转移资源的所有权而不是进行深拷贝。移动语义提高了代码的性能和效率,特别适用于处理大规模数据结构和动态内存管理。

除了以上列举的特性,C++11还引入了其他一些新功能和改进,如std::tuple(元组)、std::chrono(时间处理)、委托构造函数(delegating constructors)、标准线程库(std::thread)和正则表达式支持(std::regex)等。这些新特性使得C++11成为一个现代化、更强大的编程语言,提供了更多的工具和选项,以满足开发者的需求。

例子

以下是对C++11引入的一些新特性的简单示例:

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

    auto num = 10;  // 推导出num的类型为int
    auto name = "John";  // 推导出name的类型为const char*
    
    • 1
    • 2
  2. Lambda表达式:

    // 使用Lambda表达式求两个数的和
    auto sum = [](int a, int b) { return a + b; };
    int result = sum(5, 3);  // 结果为8
    
    • 1
    • 2
    • 3
  3. 右值引用(Rvalue references):

    std::string&& rvalueRef = std::move(std::string("Hello"));  // 将临时对象绑定到右值引用上
    
    • 1
  4. 智能指针(Smart Pointers):

    // 使用std::shared_ptr创建共享所有权的指针
    std::shared_ptr<int> sharedPtr(new int(5));
    // 使用std::unique_ptr创建独占所有权的指针
    std::unique_ptr<int> uniquePtr(new int(10));
    // 使用std::weak_ptr创建弱引用,防止循环引用
    std::weak_ptr<int> weakPtr = sharedPtr;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  5. 范围for循环(Range-based for loop):

    std::vector<int> numbers = {1, 2, 3, 4, 5};
    for (int num : numbers) {
        std::cout << num << " ";
    }
    // 输出结果: 1 2 3 4 5
    
    • 1
    • 2
    • 3
    • 4
    • 5
  6. 静态断言(static_assert):

    static_assert(sizeof(int) == 4, "int类型大小不为4字节");  // 如果条件不满足,编译错误,并输出错误消息
    
    • 1
  7. 空指针常量(nullptr):

    int* ptr = nullptr;  // 声明一个空指针
    
    • 1
  8. 并发编程支持:

    #include <iostream>
    #include <thread>
    
    // 线程函数,打印线程ID
    void printThreadId() {
        std::cout << "Thread ID: " << std::this_thread::get_id() << std::endl;
    }
    
    int main() {
        std::thread thread1(printThreadId);  // 创建线程1
        std::thread thread2(printThreadId);  // 创建线程2
    
        thread1.join();  // 等待线程1结束
        thread2.join();  // 等待线程2结束
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
  9. 移动语义(Move semantics):

    class MyString {
    public:
        MyString(std::string&& str) : data(std::move(str)) {}  // 移动构造函数
    
    private:
        std::string data;
    };
    
    std::string temp = "Hello";
    MyString myString(std::move(temp));  // 将temp的所有权转移到myString对象中
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
  10. 模板别名(template alias):

    template<typename T, typename U>
    using Pair = std::pair<T, U>;  // 定义模板别名Pair,代表std::pair<T, U>
    
    Pair<int, std::string> myPair(1, "apple");  // 使用模板别名创建Pair对象
    
    • 1
    • 2
    • 3
    • 4
  11. 可变参数模板(variadic templates):

    // 使用可变参数模板实现递归求和
    template<typename T>
    T sum(T value) {
        return value;
    }
    
    template<typename T, typename... Args>
    T sum(T first, Args... rest) {
        return first + sum(rest...);
    }
    
    int totalSum = sum(1, 2, 3, 4, 5);  // 求和结果为15
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
  12. 类型转发(perfect forwarding):

    // 完美转发函数模板
    template<typename Func, typename... Args>
    void callFunc(Func&& func, Args&&... args) {
        std::forward<Func>(func)(std::forward<Args>(args)...);
    }
    
    // 测试函数
    void printText(const std::string& str) {
        std::cout << str << std::endl;
    }
    
    std::string message = "Hello!";
    callFunc(printText, message);  // 将printText函数和message参数完美转发
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  13. std::tuple(元组):

    #include <tuple>
    #include <iostream>
    
    int main() {
        std::tuple<int, std::string, double> person(25, "Alice", 1.65);
    
        int age = std::get<0>(person);  // 获取元组第一个元素
        std::string name = std::get<1>(person);  // 获取元组第二个元素
        double height = std::get<2>(person);  // 获取元组第三个元素
    
        std::cout << "Age: " << age << std::endl;
        std::cout << "Name: " << name << std::endl;
        std::cout << "Height: " << height << std::endl;
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
  14. std::chrono(时间处理):

    #include <chrono>
    #include <thread>
    #include <iostream>
    
    int main() {
        // 计算程序执行时间
        auto start = std::chrono::high_resolution_clock::now();  // 记录起始时间
    
        std::this_thread::sleep_for(std::chrono::seconds(2));  // 模拟耗时操作,暂停2秒钟
    
        auto end = std::chrono::high_resolution_clock::now();  // 记录结束时间
        auto duration = std::chrono::duration_cast<std::chrono::seconds>(end - start);  // 计算时间差
    
        std::cout << "Program execution time: " << duration.count() << " seconds." << std::endl;
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
  15. 委托构造函数(delegating constructors):

    #include <iostream>
    
    class Rectangle {
    public:
        Rectangle(int width, int height) : width(width), height(height) {}
    
        Rectangle(int size) : Rectangle(size, size) {}  // 委托构造函数,调用其他构造函数
    
        void printArea() {
            std::cout << "Area: " << width * height << std::endl;
        }
    
    private:
        int width;
        int height;
    };
    
    int main() {
        Rectangle square(5);  // 创建一个边长为5的正方形
        square.printArea();  // 输出面积
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
  16. 正则表达式支持(std::regex):

    #include <iostream>
    #include <regex>
    
    int main() {
        std::string text = "Hello, my email is example@example.com";
        std::regex pattern(R"([\w\.-]+)@([\w\.-]+)(\.\w+)");  // 匹配邮箱地址的正则表达式模式
    
        std::smatch matches;
        if (std::regex_search(text, matches, pattern)) {  // 搜索匹配项
            std::cout << "Email found: " << matches.str() << std::endl;
        }
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

这些示例展示了C++11引入的一些有用的库和特性的基本用法。std::tuple提供了一个灵活的容器,可以存储多个元素。std::chrono提供了时间处理功能,方便进行时间相关的操作和测量。委托构造函数允许一个构造函数调用另一个构造函数来初始化对象。std::thread提供了多线程编程的支持,可以创建、控制和等待线程。std::regex提供了正则表达式支持,使得文本匹配和替换变得更加方便和强大。

这些示例展示了C++11引入的泛型编程增强特性的基本用法。通过模板别名,我们可以定义更简洁易读的模板名称。可变参数模板使得编写接受可变数量参数的函数变得更加简单和灵活。类型转发允许我们在接受参数时完美地将其转发给其他函数,保留其值类别和引用类型。

这些特性都有助于提高泛型代码的可读性、灵活性和重用性,并且非常有用于编写通用库和泛型算法。

C++14

C++14 对于 C++11 进行了一些升级,主要包括以下几个方面的改进:

  1. 泛型 Lambda 表达式:使用泛型 lambda,可以更灵活地定义匿名函数,并且可以在函数体内使用 auto 关键字进行类型推导。

  2. 二进制字面量:引入了二进制字面量,可以直接表示二进制数据,例如使用 0b 前缀表示二进制数字。

  3. 返回类型推导:函数返回类型可以使用 auto 关键字进行推导,允许在函数定义时不显式声明返回类型。

  4. constexpr 函数改进:constexpr 关键字可以用于描述函数的常量表达式特性,并且可以支持更多的操作和控制流语句。

  5. 运行时大小数组:允许在运行时创建具有动态大小的数组,使用 std::vector 进行管理。

  6. 统一的字面量语法:引入了用户自定义字面量的机制,可以自定义并使用各种单位、时间、长度等字面量。

  7. 一些小的语法改进:包括函数参数列表支持使用 ‘…’ 表示可变参数、更好的类型推导规则等。

总的来说,C++14 的改进主要着眼于语言的表达能力和编程的便捷性,使得程序员能够更加方便地编写高效、简洁的代码。

例子

下面是一些具体的例子来说明 C++14 的一些改进:

  1. 泛型 Lambda 表达式:

    // 使用泛型 lambda 将两个数相加并打印结果
    auto add = [](auto a, auto b) {
        auto sum = a + b;
        std::cout << "Sum: " << sum << std::endl;
    };
    
    add(5, 10);   // 输出: Sum: 15
    add(3.14, 2.71);   // 输出: Sum: 5.85
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  2. 二进制字面量:

    // 使用二进制字面量表示二进制数字
    int binaryNumber = 0b101010;
    std::cout << "Binary number: " << binaryNumber << std::endl;   // 输出: Binary number: 42
    
    • 1
    • 2
    • 3
  3. 返回类型推导:

    // 返回类型使用 auto 进行推导
    auto add(int a, int b) {
        return a + b;
    }
    
    auto result = add(5, 10);
    std::cout << "Result: " << result << std::endl;   // 输出: Result: 15
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  4. constexpr 函数改进:

    // 使用 constexpr 声明常量表达式函数
    constexpr int factorial(int n) {
        if (n <= 1)
            return 1;
        else
            return n * factorial(n - 1);
    }
    
    constexpr int fact5 = factorial(5);
    std::cout << "Factorial of 5: " << fact5 << std::endl;   // 输出: Factorial of 5: 120
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
  5. 运行时大小数组:

    // 在运行时创建动态大小的数组,并使用 std::vector 进行管理
    int n;
    std::cout << "Enter the size of the array: ";
    std::cin >> n;
    
    std::vector<int> dynamicArray(n);
    for (int i = 0; i < n; ++i) {
        dynamicArray[i] = i * 2;
    }
    
    std::cout << "Dynamic Array: ";
    for (auto num : dynamicArray) {
        std::cout << num << " ";   // 输出: Dynamic Array: 0 2 4 ...
    }
    std::cout << std::endl;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
  6. 用户自定义单位字面量:

    // 自定义一个长度单位字面量 Inch
    constexpr long double operator"" _inch(long double inches) {
        return inches * 2.54;   // 将英寸转换为厘米
    }
    
    // 使用自定义单位字面量进行转换
    long double length = 10.5_inch;
    std::cout << "Length in cm: " << length << std::endl;   // 输出: Length in cm: 26.67
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  7. 时间单位字面量:

    // 定义一个时间单位字面量 Seconds
    constexpr long long operator"" _s(unsigned long long seconds) {
        return seconds;
    }
    
    // 使用时间单位字面量表示不同的时间
    int main() {
        auto duration = 2_s;
        std::cout << "Duration in seconds: " << duration << std::endl;   // 输出: Duration in seconds: 2
    
        auto timeout = 30_s;
        std::cout << "Timeout in seconds: " << timeout << std::endl;     // 输出: Timeout in seconds: 30
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

这些例子展示了 C++14 的一些特性和改进,使得代码更加灵活和便捷。

C++17

C++17 相对于 C++14 进行了一些重要的升级和改进。以下是其中的一些主要特性:

  1. 结构化绑定(Structured Bindings):允许从复合类型(如 std::tuple 或数组)中提取成员,并将其绑定到命名的变量上。

    std::pair<int, std::string> p = {10, "Hello"};
    
    // 使用结构化绑定将 pair 中的成员绑定到变量中
    auto [x, str] = p;
    
    std::cout << "x: " << x << std::endl;         // 输出: x: 10
    std::cout << "str: " << str << std::endl;     // 输出: str: Hello
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  2. if 与 switch 初始化(if and switch with initializer):允许在 if 语句和 switch 语句中声明并初始化变量。

    if (int x = computeValue(); x > 0) {
        // 使用 x 进行操作
    }
    
    switch (int x = computeValue(); x) {
        case 1:
            // 处理 x = 1 的情况
            break;
        case 2:
            // 处理 x = 2 的情况
            break;
        default:
            // 其他情况
            break;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
  3. 强制拷贝消除(constexpr if):通过在编译时判断条件来消除无限递归和无用的代码分支。

    template <typename T>
    void process(T value) {
        if constexpr (std::is_integral_v<T>) {
            // 对整型进行处理
        } else if constexpr (std::is_floating_point_v<T>) {
            // 对浮点型进行处理
        } else {
            // 其他类型的处理
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
  4. 折叠表达式(Fold Expressions):允许以一种简洁的方式展开多个参数的组合表达式。

    template<typename... Args>
    auto sum(Args... args) {
        return (args + ...);
    }
    
    int result = sum(1, 2, 3, 4);   // 等价于 result = ((1 + 2) + 3) + 4
    std::cout << "Result: " << result << std::endl;   // 输出: Result: 10
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  5. 并行算法库(Parallel Algorithms Library):引入了一组新的并行算法,例如 std::for_eachstd::transform 等,并且可以利用多核处理器并行执行操作。

    std::vector<int> numbers = {1, 2, 3, 4, 5};
    
    // 使用并行算法计算所有元素的平方
    std::for_each(std::execution::par, numbers.begin(), numbers.end(), [](int& num) {
        num = num * num;
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  6. std::optional:引入了一个新的标准库类型 std::optional,用于表示可能存在或不存在的值。

    #include <optional>
    #include <iostream>
    
    std::optional<int> divide(int a, int b) {
        if (b != 0) {
            return a / b;
        } else {
            return std::nullopt;   // 表示不存在的值
        }
    }
    
    int main() {
        auto result1 = divide(10, 5);
        if (result1.has_value()) {
            std::cout << "Result1: " << result1.value() << std::endl;   // 输出: Result1: 2
        }
    
        auto result2 = divide(10, 0);
        if (!result2.has_value()) {
            std::cout << "Cannot divide by zero." << std::endl;   // 输出: Cannot divide by zero.
        }
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
  7. 类模板参数推导(Class Template Argument Deduction):允许在创建类实例时省略模板参数,编译器会根据构造函数参数进行推导。

    template<typename T>
    struct MyContainer {
        MyContainer(T value) {
            // 构造函数逻辑
        }
    };
    
    MyContainer container(42);   // 省略了模板参数,编译器根据构造函数参数推导出 T 为 int 类型
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  8. std::string_view:引入了一个非拥有性的字符串视图类型 std::string_view,用于高效地操作字符串而无需进行拷贝。

    #include <string_view>
    #include <iostream>
    
    void processString(std::string_view str) {
        std::cout << "Length: " << str.length() << std::endl;
        std::cout << "First character: " << str[0] << std::endl;
    }
    
    int main() {
        std::string myString = "Hello, World!";
        processString(myString);          // 可以传递 std::string 或字符数组等给函数
        processString("Hello, View!");    // 也可以直接传递字符串字面量
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
  9. 内联变量(Inline Variables):允许在头文件中定义内联变量,避免重定义错误和链接错误。

    // header.h
    inline int value = 42;
    
    // source.cpp
    #include "header.h"
    #include <iostream>
    
    int main() {
        std::cout << "Value: " << value << std::endl;   // 输出: Value: 42
        value = 10;   // 修改内联变量的值
        std::cout << "Value: " << value << std::endl;   // 输出: Value: 10
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
  10. 结构化绑定与元组遍历:结合使用结构化绑定和 std::tie,可以方便地遍历和访问元组成员。

    #include <tuple>
    #include <iostream>
    
    int main() {
        std::tuple<int, std::string, double> person = {25, "Alice", 170.5};
    
        // 使用结构化绑定遍历和访问元组成员
        for (const auto& [age, name, height] : {person}) {
            std::cout << "Age: " << age << std::endl;           // 输出: Age: 25
            std::cout << "Name: " << name << std::endl;         // 输出: Name: Alice
            std::cout << "Height: " << height << std::endl;     // 输出: Height: 170.5
        }
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
  11. 类型特征检查(Type Traits):引入了一些新的类型特征检查工具,例如 std::is_invocablestd::is_swappable 等,用于在编译时进行类型特性判断。

    #include <type_traits>
    #include <iostream>
    
    template<typename T>
    void process(T value) {
        if constexpr (std::is_integral_v<T>) {
            std::cout << "Integral type" << std::endl;
        } else if constexpr (std::is_floating_point_v<T>) {
            std::cout << "Floating-point type" << std::endl;
        } else {
            std::cout << "Other type" << std::endl;
        }
    }
    
    int main() {
        process(42);          // 输出: Integral type
        process(3.14);        // 输出: Floating-point type
        process("Hello");     // 输出: Other type
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
  12. 内联命名空间(Inline Namespace):允许在现有的命名空间内添加内联命名空间,用于版本管理和向后兼容。

    namespace math {
        inline namespace v1 {
            int add(int a, int b) {
                return a + b;
            }
        }
    
        inline namespace v2 {
            double add(double a, double b) {
                return a + b;
            }
        }
    }
    
    int main() {
        int result1 = math::add(2, 3);       // 调用 math::v1::add,返回 5
        double result2 = math::add(2.5, 3.7);  // 调用 math::v2::add,返回 6.2
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
  13. std::anystd::any 是一个类型安全的、堆内存分配的通用值容器,可以存储任意类型的值。

    #include <any>
    #include <iostream>
    
    int main() {
        std::any value;
    
        // 存储不同类型的值
        value = 42;
        std::cout << std::any_cast<int>(value) << std::endl;   // 输出: 42
    
        value = "Hello";
        std::cout << std::any_cast<const char*>(value) << std::endl;   // 输出: Hello
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
  14. std::filesystemstd::filesystem 提供了一组用于操作文件系统的功能,包括路径操作、文件查找、迭代目录等。

    #include <filesystem>
    #include <iostream>
    
    namespace fs = std::filesystem;   // 别名空间简化
    
    int main() {
        // 读取当前目录并打印所有文件和目录的名称
        fs::path currentPath = fs::current_path();
        for (const auto& entry : fs::directory_iterator(currentPath)) {
            std::cout << entry.path().filename() << std::endl;
        }
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
  15. std::variantstd::variant 是一个类型安全的、多态的联合类型,可以存储多个可能的类型之一。

    #include <variant>
    #include <iostream>
    #include <string>
    
    int main() {
        std::variant<int, double, std::string> value;
    
        value = 42;
        std::cout << std::get<int>(value) << std::endl;   // 输出: 42
    
        value = 3.14;
        std::cout << std::get<double>(value) << std::endl;   // 输出: 3.14
    
        value = "Hello";
        std::cout << std::get<std::string>(value) << std::endl;   // 输出: Hello
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

这些是 C++17 中的一些主要升级和改进。C++17 还包含了其他一些特性,例如文件系统库、更好的类型推导、内联变量、抛出异常的属性说明符等等,这些特性都进一步提高了 C++ 的功能和表达能力。

C++20

C++20 是 C++ 标准的最新版本,于 2020 年发布。它引入了一些重要的特性和改进,如以下所示:

  1. 概念(Concepts):概念是类型的约束,可用于在编译时验证模板参数的属性。概念使得模板更易于使用和调试,并提供更好的错误消息。

  2. 三路比较操作符(Three-Way Comparison):引入了 <=> 操作符,用于进行三路比较。这个操作符返回一个表示比较结果的值,可以方便地进行对象的等于、大于和小于比较。

  3. 协程(Coroutines):协程是一种轻量级的并发编程机制,允许在函数中暂停和恢复执行。协程通过 co_awaitco_yield 等关键字实现。

  4. 初始化列表的聚合推导(Aggregate Initialization with auto):现在可以使用 auto 推导类型进行初始化列表的聚合初始化。

  5. 合并了 std::filesystem 库:std::filesystem 库已经成为 C++20 的一部分,提供了更强大、更便捷的文件系统操作功能。

  6. Ranges 库:引入了 Ranges 库,提供了一组用于处理和操作迭代器范围的标准算法和工具函数。

  7. 数字分隔符(Digit Separators):可以在数字常量中使用分隔符 _ 来提高可读性,例如 1'000'000

  8. 其他语言改进:如对模块化编程的支持、对属性(Attribute)的增强、对线程的改进等。

这些是 C++20 中的一些重要改进和特性。C++20 的目标是提供更简洁、更安全、更高效的编程体验,并为现代软件开发带来更多的功能和灵活性。

例子

以下是 C++20 中一些重要特性的示例:

  1. 概念(Concepts):

    template <typename T>
    concept Integral = std::is_integral<T>::value;
    
    template <Integral T>
    void printNumber(T number) {
        std::cout << number << std::endl;
    }
    
    int main() {
        printNumber(42);   // 编译通过,T 要求是整型
        printNumber(3.14);   // 编译错误,T 不满足 Integral 概念
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
  2. 三路比较操作符(Three-Way Comparison):

    #include <iostream>
    #include <compare>
    
    struct Point {
        int x, y;
    
        auto operator<=>(const Point& other) const {
            return std::tie(x, y) <=> std::tie(other.x, other.y);
        }
    };
    
    int main() {
        Point p1{1, 2};
        Point p2{3, 4};
    
        auto result = p1 <=> p2;
        if (result < 0) {
            std::cout << "p1 is less than p2" << std::endl;
        } else if (result > 0) {
            std::cout << "p1 is greater than p2" << std::endl;
        } else {
            std::cout << "p1 is equal to p2" << std::endl;
        }
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
  3. 协程(Coroutines):

    #include <iostream>
    #include <coroutine>
    
    struct Generator {
        struct promise_type {
            int current_value;
    
            auto initial_suspend() { return std::suspend_always{}; }
            auto final_suspend() noexcept { return std::suspend_always{}; }
            auto yield_value(int value) {
                current_value = value;
                return std::suspend_always{};
            }
            auto return_void() {}
            Generator get_return_object() { return Generator{this}; }
        };
    
        struct iterator {
            std::coroutine_handle<promise_type> coroutine;
    
            iterator& operator++() {
                coroutine.resume();
                if (coroutine.done()) {
                    coroutine.destroy();
                }
                return *this;
            }
    
            int operator*() const {
                return coroutine.promise().current_value;
            }
    
            bool operator==(std::default_sentinel_t) const {
                return coroutine.done();
            }
        };
    
        explicit Generator(promise_type* promise) :
            coroutine(std::coroutine_handle<promise_type>::from_promise(*promise)) {}
    
        ~Generator() {
            if (coroutine) {
                coroutine.destroy();
            }
        }
    
        iterator begin() {
            coroutine.resume();
            return iterator{coroutine};
        }
        std::default_sentinel_t end() {
            return std::default_sentinel;
        }
    
        std::coroutine_handle<promise_type> coroutine;
    };
    
    Generator generateNumbers() {
        co_yield 1;
        co_yield 2;
        co_yield 3;
    }
    
    int main() {
        for (auto num : generateNumbers()) {
            std::cout << num << std::endl;
        }
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
  4. 初始化列表的聚合推导(Aggregate Initialization with auto):

    #include <iostream>
    #include <vector>
    
    int main() {
        auto numbers = {1, 2, 3, 4, 5};   // 推导为 std::initializer_list<int>
    
        for (auto num : numbers) {
            std::cout << num << " ";
        }
        std::cout << std::endl;
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  5. 合并了 std::filesystem 库:

    #include <iostream>
    #include <filesystem>
    
    int main() {
        std::filesystem::path currentPath = std::filesystem::current_path();
        std::cout << "Current Path: " << currentPath << std::endl;
    
        if (std::filesystem::exists(currentPath)) {
            std::cout << "Path exists." << std::endl;
        }
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  6. Ranges 库:

    #include <iostream>
    #include <vector>
    #include <ranges>
    
    int main() {
        std::vector<int> numbers{1, 2, 3, 4, 5};
    
        auto evenNumbers = numbers | std::views::filter([](int num) { return num % 2 == 0; });
        for (auto num : evenNumbers) {
            std::cout << num << " ";
        }
        std::cout << std::endl;
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
  7. 数字分隔符(Digit Separators):

    #include <iostream>
    
    int main() {
        int million = 1'000'000;
        long long billion = 10'000'000'000;
    
        std::cout << "Million: " << million << std::endl;
        std::cout << "Billion: " << billion << std::endl;
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
  8. 模块(Modules):

    // math.cppm
    export module math;
    
    export int add(int a, int b) {
        return a + b;
    }
    
    // main.cpp
    import math;
    
    int main() {
        int result = add(2, 3);
        // 其他操作
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
  9. std::span 类型:

    #include <iostream>
    #include <vector>
    #include <span>
    
    void printValues(std::span<int> values) {
        for (const auto& value : values) {
            std::cout << value << " ";
        }
        std::cout << std::endl;
    }
    
    int main() {
        std::vector<int> numbers{1, 2, 3, 4, 5};
    
        printValues(numbers);
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

这些示例展示了 C++20 中概念、三路比较操作符和协程的用法,它们是 C++20 中引入的一些重要特性,为开发者带来了更多的便利性和表达能力。当然,还有其他特性在 C++20 中,这里只是列举了一部分示例。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/正经夜光杯/article/detail/917562
推荐阅读
相关标签
  

闽ICP备14008679号