c++20新特性
包括对并发编程的支持(例如std::jthread)、对日期和时间处理的增强(std::chrono)以及其他一些新的容器和算法。这些改进使得lambda表达式在C++20中变得更加强大和灵活,能够处理更多种类的编程任务,并提供更高的表达能力和性能。这简化了对集合的操作,例如使用范围for循环来处理数据。通过operator运算符,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中变得更加强大和灵活,能够处理更多种类的编程任务,并提供更高的表达能力和性能。
更多推荐
所有评论(0)