C++ 20 & C++ 23 部分新功能
收录不全面,为日常给 OIer 在 洛谷(支持 C++20 但不支持 C++ 23/Hydro(支持 C++ 20 & 23)等做题用。
C++ 20
从 GCC 8 开始支持,未完全支持。
三路比较运算符(<=>)
是一种运算符(废话)。
但他返回的不是 bool 值,而是 std::strong_ordering 或 std::partial_ordering。
如果操作数之一是 bool 类型而另一个不是,那么程序非良构。
如果需要进行除了从整数类型到浮点数类型之外的窄化转换,那么程序非良构。
-
如果各操作数均具有整数类型,那么运算符产出
std::strong_ordering类型的值:- 如果两个操作数算术上相等则为
std::strong_ordering::equal。 - 如果第一操作数算术上小于第二个则为
std::strong_ordering::less。 - 否则为
std::strong_ordering::greater。
- 如果两个操作数算术上相等则为
-
如果各操作数为浮点数类型,那么运算符产出
std::partial_ordering类型的值:-
如果
a < b 则为std::partial_ordering::less。 -
如果
a > b 则为std::partial_ordering::greater。 -
如果
a = b 则为std::partial_ordering::equivalent。 -
否则为
std::partial_ordering::unordered(无序)。
-
范围 for 中的初始化语句和初始化器
开始支持 init-statement,可以在 for 循环的初始化部分声明变量。
人话:范围 for 循环语句支持初始化语句。
示例:
for(int i = 0; pair<int, int> j : Map)
日历功能
-
初始化 年、月、日:
auto y1 = year {2019}; auto y2 = 2019y; auto m1 = month {9}; auto m2 = September; auto d1 = day {18}; auto d2 = 18d; -
完整日期
year_mouth_day fdt1 {2019y, September, 18d}; auto fdt2 = 2019y / September / 18d; year_mouth_day fdt3 {Monday[3] / September / 2019};如果让刚入门的 OI 初学者知道会怎么样。
格式化库 (std::format)
头文件 <format>。
示例:
std::string s = std::format("Hello, world!\n");
// == "Hello, world!\n"
std::string s = std::format("The answer is {}.", 42);
// == "The answer is 42."
std::string s = std::format("I'd rather be {1} than {0}.", "right", "happy");
// == "I'd rather be happy than right."
std::vector<int> v = {1, 2, 3};
std::string s = fmt::print("{}\n", v);
// == "[1, 2, 3]"
数学常数
_Tp 填入数据类型(如 double):
-
std::numbers::e_v<_Tp>:数学常数e 。 -
std::numbers::ln2_v<_Tp>:\ln 2 。 -
std::numbers::ln10_v<_Tp>:\ln 10 。 -
std::numbers::sqrt2_v<_Tp>:\sqrt{2} 。 -
std::numbers::sqrt3_v<_Tp>:\sqrt{3}
函数
-
midpoint()-
midpoint(T a, T b):\frac{a + b}{2} 向a 取整。 -
midpoint(T * a, T * b):若a 与b 分别指向同一数组对象x 的x[i]与x[j],则返回指向x[std::midpoint(i, j)]。
-
C++ 23
if consteval
指在编译阶段可以可以进行条件编译,并根据结果选择可以编译或者不编译哪些代码块。
if consteval {} else {}
if !consteval {} else {}
多维下标运算符
大白话:重载数组下标。
struct Matrix4f {
float m[4][4];
float * const operator [] (const int i) { return m[i]; }
};
标记不可达代码 (std::unreachable)
标记程序中不可达的代码部分,帮助编译器进行更激进的优化。通过明确标记不可达的代码,编译器可以进行更有效的优化和错误检查,减少不必要的警告或误报。
与 exit(0) 不同,exit(0) 是程序运行时推出但仍需编译,而 std::unreachable(); 是编译都不编译了。
平台无关的假设 ([[assume]])
[[assume]] 属性允许开发者在代码中声明某些条件总是为真,帮助编译器进行更好的优化。
int divide(int a, int b)
{
[[assume(b != 0)]];
return a / b;
}
命名通用字符转义
'\N{WHITE SMILING FACE}' WHITE SMILING FACE 是 Unicode 字符的名字,对应的 Unicode 码点是 U+263A。
新容器:flat_map 和 flat_set
真正有用的东西来了!
性能优化的平面映射 (flat_map) 和集合 (flat_set) 容器。
使用连续的内存块存储元素,从而减少了内存分配和访问时间。
适合于频繁查找操作的场景。
运行时堆栈跟踪
头文件 <stacktrace>
std::stacktrace::current()
示例输出:
foo() at example.cpp:5
main() at example.cpp:10
print 与 println
类似于 format()(C++ 20)。
println 比 print 多了一个换行符。