当前位置: 首页 > article >正文

C++学习(十)(标准,C++11 和 C++14,C++17,C++20)

C++ 标准

C++ 标准是一组定义语言功能、语法和语义的规则和准则。国际标准化组织 (ISO) 负责维护和更新 C++ 标准。这些标准的主要目的是确保跨多个平台和编译器的一致性、效率和可维护性。

以下是迄今为止发布的不同 C++ 标准的简要摘要:

  • C++98/C++03:C++ 的第一个标准化版本,引入了许多功能,如模板、异常和标准模板库 (STL)。C++03 是对 C++98 的次要更新,修复了一些错误并改进了性能。

  • C++11:对语言的重大升级,引入了以下功能:

    • Lambda 表达式:
    auto sum = [](int a, int b) -> int { return a + b; };
    • 基于范围的 for 循环:
    std::vector<int> numbers = {1, 2, 3, 4};
    for (int num : numbers) {
        std::cout << num << std::endl;
    }
    • 智能指针(如 和 )。std::shared_ptrstd::unique_ptr
  • C++14:对 C++11 进行了一次次要更新,其中添加了如下功能:

    • 通用 lambda 表达式:
    auto generic_sum = [](auto a, auto b) { return a + b; };
    • 二进制文本:
    int binary_number = 0b1010;
  • C++17:另一个重大更新,引入了如下功能:

    • if和初始值设定项:switch
    if (auto it = my_map.find(key); it != my_map.end()) {
        // use 'it' here
    }
    
    • 结构化绑定:
    std::map<std::string, int> my_map = {{"A", 1}, {"B", 2}};
    for (const auto& [key, value] : my_map) {
        // use 'key' and 'value' here
    }
  • C++20:该语言的最新重大更新,具有以下功能:

    • 概念:
    template<typename T>
    concept Addable = requires(T a, T b) {
        { a + b } -> std::same_as<T>;
    };
    • 范围:
    std::vector<int> numbers = {1, 2, 3, 4};
    auto doubled = numbers | std::views::transform([](int n) { return n * 2; });
    • 协程等。

请记住,要使用这些语言功能,您可能需要将编译器配置为使用特定的 C++ 标准版本。例如,对于 GCC 或 Clang,您可以使用 、 、 或 标志。-std=c++11-std=c++14-std=c++17-std=c++20

C++11 和 C++14

C++11C++11 标准,也称为 C++0x,于 2011 年 9 月正式发布。它引入了几项新的语言功能和改进,包括:

  • Auto:允许编译器根据变量的初始化表达式推断变量类型。

    auto integer = 42; // integer is of int type
    auto floating = 3.14; // floating is of double type
    
  • 基于范围的 for 循环:提供类似于 foreach 的语义,用于迭代容器或数组。

    std::vector<int> numbers {1, 2, 3, 4};
    for (int number : numbers) {
        std::cout << number << std::endl;
    }
    
  • Lambda 函数:允许更轻松地创建函数对象的匿名函数。

    auto add = [](int a, int b) -> int { return a + b; };
    int sum = add(42, 13); // sum is equal to 55
    
  • nullptr:一个表示 null 指针的新关键字,比使用文本 '0' 或 “NULL” 更类型安全。

    int *ptr = nullptr;
    
  • 线程支持库:提供一种使用线程和跨线程同步数据访问的标准方法。

    std::thread t([]() { std::cout << "Hello from another thread\n"; });
    t.join();
    

C++14C++14 标准于 2014 年 12 月正式发布,作为 C++11 的小型扩展,更侧重于微调语言功能和修复问题。引入的一些新功能:

  • 通用 Lambda:允许使用 'auto' 类型占位符声明 lambda 函数参数。

    auto add = [](auto a, auto b) { return a + b; };
    auto sum_i = add(42, 13); // Still works with integers
    auto sum_f = add(3.14, 2.72); // Now works with doubles too
    
  • Binary Literals(二进制文本):允许您将整数作为二进制文本输入,以提高可读性。

    int b = 0b110101; // Decimal value is 53
    
  • decltype(auto):推导变量的类型以匹配初始化变量时使用的表达式的类型。

    auto func = [](auto a, auto b) { return a * b; };
    decltype(auto) result = func(5, 3.14); // decltype(auto) deduces to "double"
    
  • 变量模板:允许您使用模板参数定义变量。

    template <typename T>
    constexpr T pi = T(3.1415926535897932385);
    float r = pi<float>; // Instantiated as a float
    double d = pi<double>; // Instantiated as a double

 

C++20

C++20 是 C++ 编程语言的最新标准,它为语言带来了重大改进和新功能。此版本旨在促进更好的软件开发实践,并使开发人员能够编写更高效、可读和可维护的代码。

以下是 C++20 中引入的一些关键功能:

概念

概念是一种对模板参数强制实施特定要求的方法,允许您编写更具表现力和可理解性的代码。它们改进了使用模板时的错误消息,并确保模板参数满足特定条件。

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;
}

范围

范围提供了一种处理值序列的新方法,增强了标准库算法的功能和表现力。基于范围的算法使使用序列变得更加容易和方便。

#include <algorithm>
#include <iostream>
#include <ranges>
#include <vector>

int main() {
    std::vector<int> numbers = { 1, 2, 3, 4, 5 };

    auto even_numbers = numbers | std::views::filter([](int n) { return n % 2 == 0; });

    for (int n : even_numbers) {
        std::cout << n << ' ';
    }
}

协程

协程是一种编写异步和并发代码的新方法,具有更高的可读性。它们允许暂停和恢复函数,使您能够编写更高效、无阻塞的代码。

#include <coroutine>
#include <iostream>
#include <future>

std::future<int> async_value(int value) {
    co_await std::chrono::seconds(1);
    co_return value * 2;
}

int main() {
    auto result = async_value(42);
    std::cout << "Result: " << result.get() << std::endl;
}

我们可以用**“定时烹饪任务”**的比喻来理解这段代码的异步协程机制:


代码拆解

1. 创建定时烹饪任务(协程函数)

std::future<int> async_value(int value) {
    co_await std::chrono::seconds(1); // 暂停1秒(定时器)
    co_return value * 2;              // 返回结果(完成烹饪)
}
 
  • co_await
    像给厨房设定一个定时器,在等待的1秒钟里,厨师(主线程)可以去做其他事情(不阻塞)。

  • co_return
    定时器响后,自动继续执行,返回加工后的结果(把原料 value 翻倍)。


2. 启动任务并获取结果

int main() {
    auto result = async_value(42);       // 开始烹饪(启动协程)
    std::cout << "Result: " << result.get() << std::endl; // 等待结果
}
 
  • result.get()
    相当于等待厨师完成烹饪,如果结果还没准备好(定时未到),主线程会在这里暂停等待。


类比场景

想象你让智能厨房做菜:

  1. 下达指令
    async_value(42) 相当于说:“把42克食材处理一下,1小时后给我结果”。

  2. 异步等待
    厨房定时器开始倒计时,你可以去刷手机(主线程不阻塞)。

  3. 获取结果
    1小时后,你调用 result.get() 取回加工好的84克成品。


关键知识点

代码部分作用类比
std::future<int>表示未来将获得一个整数结果烹饪订单凭据
co_await暂停协程,让出线程资源设定厨房定时器
co_return协程完成时返回结果厨师交付成品
result.get()阻塞等待结果等待厨师完成

实际执行流程

  1. 调用 async_value(42) 启动协程:

    • 遇到 co_await → 暂停协程,启动1秒定时器。

    • 立刻返回 future 对象(此时结果尚未准备好)。

  2. 主线程执行 result.get()

    • 如果1秒未到 → 主线程阻塞等待

    • 1秒后定时器触发 → 协程恢复,计算 42*2=84 并存入 future

    • 主线程获得结果,输出 Result: 84


注意事项

  1. 协程依赖:需要 C++20 或更高标准,且编译器支持协程(如 GCC11+/Clang14+)。

  2. 不完全是多线程:协程的暂停/恢复在单线程内也可实现(本例通过定时器演示异步,实际可能涉及线程池)。

  3. 错误处理:真实场景需处理协程中可能的异常(本例未展示)。


一句话总结

这段代码像**“智能厨房点单”**——主线程下单后继续干活,协程默默计时处理,最后交付结果,高效利用等待时间! 🕒👨🍳

和 关键字constexpr consteval

和 都与编译时评估有关。标记为 的函数可以在编译时或运行时执行,而标记为 的函数只能在编译时执行。constexpr consteval constexpr consteval

constexpr int add(int a, int b) {
    return a + b;
}

consteval int square(int x) {
    return x * x;
}

int main() {
    constexpr int result1 = add(3, 4);   // evaluated at compile-time
    int result2 = add(5, 6);             // evaluated at runtime
    constexpr int result3 = square(7);   // evaluated at compile-time
}

这些只是 C++20 标准的一些亮点。它还包括许多其他功能和改进,例如结构化绑定、改进的 lambda 和新的标准库组件。总体而言,C++20 使开发人员能够更轻松地编写干净、高效且富有表现力的代码。
 

我们可以用**“建筑设计”“施工阶段”**的比喻来理解这两个关键字:


核心区别

关键字作用阶段比喻灵活性
constexpr编译时 或 运行时设计蓝图(可调整)灵活,能适应不同阶段
consteval仅编译时设计规范(必须确定)严格,仅设计阶段

详细解释

1. constexpr(灵活的双面手)
  • 功能:可以用于编译时计算,也可以在运行时当普通函数调用。

  • 场景

    • 编译时:比如计算数组长度、模板参数等需要提前确定的值。

    • 运行时:当输入参数只能在运行时确定时,自动降级为普通函数。

代码示例

constexpr int 平方(int x) {
    return x * x;
}

int main() {
    constexpr int a = 平方(5);  // 编译时计算(设计阶段确定)
    int b = 平方(10);           // 运行时计算(施工阶段执行)
}
 

2. consteval(严格的编译时警察)
  • 功能:强制函数必须在编译时执行,否则直接报错。

  • 场景

    • 必须确保某个值在编译时确定(如模板元编程中的常量)。

    • 避免运行时开销,确保优化。

代码示例

consteval int 立方(int x) {
    return x * x * x;
}

int main() {
    constexpr int a = 立方(3); // 合法(编译时计算)
    int b = 立方(5);           // ❌ 编译错误(不能在运行时调用!)
}
 

对比场景

假设你是一个建筑师:

  • constexpr 像可调节的蓝图工具

    • 可以在设计阶段(编译时)计算房间面积。

    • 也可以在施工时(运行时)根据现场测量临时计算。

  • consteval 像严格的设计规范检查器

    • 必须在设计阶段确定所有参数(如承重墙位置)。

    • 施工阶段不允许临时修改,否则直接停工!


为什么需要 consteval

  • 安全强制:确保某些关键计算(如加密密钥生成)不会泄露到运行时。

  • 优化保证:编译时计算的结果可直接内联,提升性能。

  • 错误前置:在编译阶段发现问题,避免运行时崩溃。


一句话总结

  • constexpr灵活多面手,编译时和运行时都能干活。

  • consteval严格检查员,只允许编译时干活! 🔧⚡


http://www.kler.cn/a/577277.html

相关文章:

  • 基于Spring Boot + Vue的图书个性化推荐系统(LW+PPT)
  • Pandas使用笔记
  • 【Go学习实战】03-2-博客查询及登录
  • Docker基础篇——Ubuntu下Docker安装
  • function uuid_generate_v4()不存在(二)
  • Vue3实战学习(IDEA中打开、启动与搭建Vue3工程极简脚手架教程(2025超详细教程)、Windows系统命令行启动Vue3工程)(2)
  • Computational Linguistics期刊全解析:领域顶刊的投稿指南与学术价值
  • 最长递增子序列--蓝桥oj3046拍照
  • Python爬虫:爬虫基础知识
  • python爬虫系列课程7:ajax
  • SQLiteStudio:一款免费跨平台的SQLite管理工具
  • 【由技及道】量子构建交响曲:Jenkinsfile流水线的十一维编程艺术【人工智障AI2077的开发日志008】
  • 用CMake编译glfw进行OpenGL配置,在Visual Studio上运行
  • docker装Oracle
  • 2025年主流原型工具测评:墨刀、Axure、Figma、Sketch
  • RAG技术深度解析:从基础Agent到复杂推理Deep Search的架构实践
  • Baklib驱动企业知识资产增值
  • 12.【线性代数】——图和网络
  • Go小技巧易错点100例(二十四)
  • 时间复杂度空间复杂度