c++20新特性

C++20引入了许多令人兴奋的新特性和改进,这些特性使得C++语言更加现代化和强大。以下例子,演示了C++20中一些主要新特性的使用:
Concepts (概念):
Concepts允许程序员定义对类型进行约束的模板参数,以替代旧的模板元编程技术。这使得模板代码更加清晰和易于理解。

template <typename T>
concept Integral = std::is_integral_v<T>;

template <Integral T>
T add(T a, T b) {
    return a + b;
}

int main() {
    int result = add(3, 5); // 编译器检查 T 必须是 Integral 类型
    return 0;
}

Ranges (范围):
Ranges提供了一组新的库组件,用于处理和操作迭代器范围。这简化了对集合的操作,例如使用范围for循环来处理数据。

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

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

    // 使用范围for循环和ranges进行操作
    for (int num : numbers | std::views::filter([](int n) { return n % 2 == 0; })) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

Coroutines (协程):
协程是一种轻量级的并发机制,允许函数在执行期间暂停和恢复。这对于异步编程和事件驱动的应用程序特别有用。

#include <iostream>
#include <coroutine>

struct Generator {
    struct promise_type {
        int current_value;

        Generator get_return_object() {
            return Generator{std::coroutine_handle<promise_type>::from_promise(*this)};
        }
        std::suspend_always initial_suspend() { return {}; }
        std::suspend_always final_suspend() noexcept { return {}; }
        void return_void() {}
        std::suspend_always yield_value(int value) {
            current_value = value;
            return {};
        }
        void unhandled_exception() {}
    };

    bool move_next() {
        coro.resume();
        return !coro.done();
    }

    int current_value() { return coro.promise().current_value; }

    ~Generator() { coro.destroy(); }

private:
    Generator(std::coroutine_handle<promise_type> handle) : coro(handle) {}
    std::coroutine_handle<promise_type> coro;
};

Generator generate_numbers(int start, int end) {
    for (int i = start; i <= end; ++i)
        co_yield i;
}

int main() {
    Generator gen = generate_numbers(1, 5);
    while (gen.move_next()) {
        std::cout << gen.current_value() << " ";
    }
    std::cout << std::endl;

    return 0;
}

Modules (模块):
模块系统取代了传统的头文件包含方式,提供了更好的编译时间性能和更强的封装性。这可以减少编译时间和解决头文件依赖的一些问题。

// MathLib.cppm
export module MathLib;

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

// Main.cpp
import MathLib;

int main() {
    int result = add(3, 5); // 直接使用模块导出的函数
    return 0;
}

Initialization improvements (初始化改进):
C++20引入了更灵活和一致的初始化语法,包括聚合初始化的扩展和类类型的默认成员初始化。

  • 聚合初始化的扩展
struct Point {
    int x;
    int y;
    int z;
};

int main() {
    Point p1{1, 2, 3};  // 正常的聚合初始化
    Point p2{.x = 4, .y = 5, .z = 6};  // 使用指定成员初始化(仅限C++20)

    return 0;
}
  • 类类型的默认成员初始化
struct Rectangle {
    int width = 5;   // 默认成员初始化
    int height = 10; // 默认成员初始化
};

int main() {
    Rectangle r;
    std::cout << "Width: " << r.width << ", Height: " << r.height << std::endl;

    return 0;
}

Three-way comparison (三路比较):
通过operator<=>运算符,C++20引入了一种标准的方法来定义类型的三路比较,这简化了自定义类型的比较操作。

#include <iostream>

struct Point {
    int x, y;

    auto operator<=>(const Point&) const = default; // 自动生成三路比较运算符
};

int main() {
    Point p1{1, 2};
    Point p2{1, 2};

    if (p1 == p2) {
        std::cout << "Points are equal.\n";
    } else {
        std::cout << "Points are not equal.\n";
    }

    return 0;
}

Constexpr improvements (常量表达式改进):
C++20扩展了constexpr的能力,使其可以涵盖更多的语言上下文,例如动态内存分配和虚拟函数。

constexpr int fibonacci(int n) {
    if (n <= 1) return n;
    else return fibonacci(n-1) + fibonacci(n-2);
}

int main() {
    constexpr int result = fibonacci(5); // 在编译期计算 fibonacci(5)
    static_assert(result == 5, "Fibonacci of 5 should be 5");
    
    return 0;
}

New standard library features (新标准库特性):
包括对并发编程的支持(例如std::jthread)、对日期和时间处理的增强(std::chrono)以及其他一些新的容器和算法。

  • std::span 提供了一种非拥有、零开销的视图,用于表示连续的数据序列。它可以用来代替传统的裸指针和长度对,提高代码的安全性和可读性。
#include <iostream>
#include <span>

void print_span(std::span<int> s) {
    for (int& elem : s) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;
}

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    std::span<int> arr_span(arr);

    print_span(arr_span);

    return 0;
}
  • std::jthread 是一个支持取消、等待和通知的可加入线程(joinable thread)。它对比 std::thread 提供了更好的异常安全性和线程生命周期管理。
#include <iostream>
#include <thread>
#include <chrono>

void thread_func() {
    std::cout << "Thread is running...\n";
    std::this_thread::sleep_for(std::chrono::seconds(2));
    std::cout << "Thread finished.\n";
}

int main() {
    std::jthread t(thread_func);  // 使用 std::jthread 创建线程

    // 主线程等待 jthread 完成
    t.join();

    return 0;
}
  • std::chrono 增强了对日期、时间和时钟的支持,包括对日历、定时器和更精确的时钟功能的改进。
#include <iostream>
#include <chrono>

int main() {
    // 获取当前时间点
    auto now = std::chrono::system_clock::now();

    // 将时间点转换为时间字符串
    std::time_t now_c = std::chrono::system_clock::to_time_t(now);
    std::cout << "Current time: " << std::ctime(&now_c);

    // 使用日期和时间点进行算术运算
    auto later = now + std::chrono::hours(24);
    std::cout << "Tomorrow will be: " << std::ctime(&std::chrono::system_clock::to_time_t(later));

    return 0;
}
  • std::format 提供了类型安全、本地化和可扩展的格式化输出功能,类似于其他语言中的字符串格式化工具。
#include <iostream>
#include <format>

int main() {
    int number = 42;
    std::string name = "Alice";

    // 使用 std::format 进行字符串格式化
    std::cout << std::format("Hello, {}! The answer is {}.\n", name, number);

    return 0;
}

Improvements to lambdas (lambda表达式改进):
Lambda表达式现在可以用于非泛型上下文,允许它们具有重载运算符和constexpr的能力。

  • 支持非泛型的lambda参数
#include <iostream>

auto add = [](auto a, auto b) {
    return a + b;
};

int main() {
    int result_int = add(3, 5);        // 参数推导为 int
    double result_double = add(2.5, 3); // 参数推导为 double

    std::cout << "Result int: " << result_int << std::endl;
    std::cout << "Result double: " << result_double << std::endl;

    return 0;
}
  • 支持默认捕获初始化
#include <iostream>

int main() {
    int x = 10;
    auto lambda = [y = x + 1]() {
        std::cout << "Captured value: " << y << std::endl;
    };

    lambda(); // 输出 Captured value: 11

    return 0;
}
  • constexpr lambda
#include <iostream>

int main() {
    constexpr auto square = [](int x) constexpr {
        return x * x;
    };

    constexpr int result = square(5);
    std::cout << "Square of 5 is: " << result << std::endl;

    return 0;
}
  • 支持虚拟函数
#include <iostream>

struct Base {
    virtual void display() const {
        std::cout << "Base display()\n";
    }
};

int main() {
    Base b;

    auto lambda = [&b]() {
        b.display();
    };

    lambda(); // 调用虚拟函数

    return 0;
}

Others (其他):
还有许多小的语法改进、标准库的增强以及对现有特性的修正,如consteval、删除的拷贝构造函数、迭代器检查器等。
这些改进使得lambda表达式在C++20中变得更加强大和灵活,能够处理更多种类的编程任务,并提供更高的表达能力和性能。

  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值