关于C++20新特性及其使用

大家好,我是大李。

最新的C++版本是C++20,你有了解过C++20添加了哪些新特性吗?

1 模块(Modules)

改变了组织源码文件的方式,无需再区分.h 和.cpp 文件

2 协程(Coroutines)

可以暂停执行然后在未来的某个时间点恢复执行的函数,能方便地编写异步代码。

在 C++20 中,可以使用 库中的相关函数来实现暂停执行然后在未来某个时间点恢复执行,方便地编写异步代码。

// 定义一个异步任务的协程
#include <coroutine>
#include <iostream>
#include <chrono>

struct AsyncTask {
    struct promise_type {
        AsyncTask get_return_object() { return AsyncTask{Handle::from_promise(*this)}; }
        std::suspend_always initial_suspend() { return {}; }
        std::suspend_always final_suspend() noexcept { return {}; }
        void return_void() {}
        void unhandled_exception() {}
    };
    using Handle = std::coroutine_handle<promise_type>;
    AsyncTask(Handle h) : handle(h) {}
    Handle handle;
};

AsyncTask asyncOperation() {
    std::cout << "任务开始" << std::endl;
    co_await std::suspend_always{};
    std::this_thread::sleep_for(std::chrono::seconds(2));
    std::cout << "任务恢复执行" << std::endl;
}

int main() {
    AsyncTask task = asyncOperation();
    task.handle.resume();
}

在上述示例中,asyncOperation 函数是一个异步任务,通过 co_await std::suspend_always{} 实现了暂停执行。在 main 函数中,通过 task.handle.resume() 来恢复执行。

3 范围(Ranges)

提供了类似于迭代器的功能,且具有类型安全特性,其相关概念------管道操作符可提升代码可读性,并且直接进行惰性计算,不会产生中间数组。以下是关于范围的示例:

范围 for 循环

std::vector<int> numbers = {1, 2, 3, 4, 5};
for (int num : numbers) {
    std::cout << num << " ";
}

使用范围算法

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

int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5};
    // 过滤出偶数
    auto evenNumbers = numbers | std::views::filter([](int num) { return num % 2 == 0; });
    for (int num : evenNumbers) {
        std::cout << num << " ";
    }
}

范围转换

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

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

    // 将每个数乘以 2
    auto doubledNumbers = numbers | std::views::transform([](int num) { return num * 2; });

    for (int num : doubledNumbers) {
        std::cout << num << " ";
    }
}

范围的引入大大简化了对数据集合的操作,提高了代码的可读性和简洁性。

4 概念与约束

用于对模板参数进行更灵活的限制和约束,减小了对模板类型的限制,使模板参数的限制和规范在编译期更清晰、灵活。

5 指定初始化

提供了更灵活的对象初始化方式。

类内成员初始化的改进

class MyClass {
    int member1{42};  // 直接初始化成员
    std::string member2 = "Hello";  // 初始化字符串成员
};

使用 std::initializer_list 进行初始化

class Container {
public:
    Container(std::initializer_list<int> values) {
        for (auto value : values) {
            // 处理初始化列表中的值
        }
    }
};
Container c = {1, 2, 3};  // 使用初始化列表初始化对象

委托构造函数

class MyClass {
public:
    MyClass(int x, int y) : data{x + y} {}
    MyClass(int x) : MyClass(x, 0) {}  // 委托给另一个构造函数
private:
    int data;
};

这些新的初始化方式使得代码更加简洁、直观,并且提高了代码的可读性和可维护性。

6 操作符

<=> 操作符用于定义三路比较,!=== 是一个新的不等于操作符。

<=>

它主要用于为自定义类型提供一种简洁且统一的比较方式。

通过定义 <=> 运算符,你可以方便地确定两个对象之间的顺序关系。

返回值类型通常是 std::strong_orderingstd::weak_orderingstd::partial_ordering

std::strong_ordering::less :表示左边的对象小于右边的对象。

std::strong_ordering::greater :表示左边的对象大于右边的对象。

std::strong_ordering::equal :表示两个对象相等。

!===

它的作用类似于传统的 !=运算符,但在某些情况下可能提供更清晰和明确的语义表达。

7 constexpr 支持

扩展了 constexpr 在 new/delete、dynamic_cast、try/catch、虚拟等方面的能力。

8 constexpr 向量和字符串

可以在常量表达式中使用向量和字符串。

#include <iostream>
#include <string>
#include <vector>

consteval std::vector<int> createVector() {
    return {1, 2, 3};
}

consteval std::string createString() {
    return "Hello, C++20!";
}

int main() {
    constexpr auto vec = createVector();
    constexpr auto str = createString();
    for (const auto& num : vec) {
        std::cout << num << " ";
    }
    std::cout << std::endl;
    std::cout << str << std::endl;
    return 0;
}

在上述示例中,createVector 函数和 createString 函数被标记为 consteval,表示它们在常量表达式中计算并返回一个向量和一个字符串。然后在 main 函数中,以常量表达式的方式使用这些返回值。

9 计时

增加了日历、时区支持。可以使用 库的新特性来实现计时功能。

#include <iostream>
#include <chrono>

int main() {
    // 开始计时
    auto start = std::chrono::steady_clock::now();
    // 执行一些耗时操作
    for (int i = 0; i < 1000000; ++i) {
        // 一些计算或操作
    }
    // 结束计时
    auto end = std::chrono::steady_clock::now();
    // 计算时间差
    std::chrono::duration<double> elapsed_seconds = end - start;
    std::cout << "耗时: " << elapsed_seconds.count() << " 秒" << std::endl;
    return 0;
}

在上述示例中,使用 std::chrono::steady_clock::now() 获取当前时间点,然后通过计算时间差来得到操作所花费的时间。

关于C++20的新特性还有哪些呢?欢迎留言讨论!!!

往期精选

本文由mdnice多平台发布

相关推荐
fhvyxyci几秒前
【C++之STL】摸清 string 的模拟实现(下)
开发语言·c++·string
C++忠实粉丝13 分钟前
计算机网络socket编程(4)_TCP socket API 详解
网络·数据结构·c++·网络协议·tcp/ip·计算机网络·算法
古月居GYH24 分钟前
在C++上实现反射用法
java·开发语言·c++
Betty’s Sweet27 分钟前
[C++]:IO流
c++·文件·fstream·sstream·iostream
敲上瘾41 分钟前
操作系统的理解
linux·运维·服务器·c++·大模型·操作系统·aigc
不会写代码的ys1 小时前
【类与对象】--对象之舞,类之华章,共绘C++之美
c++
兵哥工控1 小时前
MFC工控项目实例三十二模拟量校正值添加修改删除
c++·mfc
长弓聊编程1 小时前
Linux系统使用valgrind分析C++程序内存资源使用情况
linux·c++
cherub.1 小时前
深入解析信号量:定义与环形队列生产消费模型剖析
linux·c++
暮色_年华1 小时前
Modern Effective C++item 9:优先考虑别名声明而非typedef
c++