专栏文章

C++ 20 & C++ 23 部分新功能

科技·工程参与者 8已保存评论 8

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
7 条
当前快照
1 份
快照标识符
@miqsp5kf
此快照首次捕获于
2025/12/04 10:06
3 个月前
此快照最后确认于
2025/12/04 10:06
3 个月前
查看原文
收录不全面,为日常给 OIer 在 洛谷(支持 C++20 但不支持 C++ 23/Hydro(支持 C++ 20 & 23)等做题用。

C++ 20

从 GCC 8 开始支持,未完全支持。

三路比较运算符(<=>

是一种运算符(废话)。
但他返回的不是 bool,而是 std::strong_orderingstd::partial_ordering
如果操作数之一是 bool 类型而另一个不是,那么程序非良构。
如果需要进行除了从整数类型到浮点数类型之外的窄化转换,那么程序非良构。
  • 如果各操作数均具有整数类型,那么运算符产出 std::strong_ordering 类型的值:
    • 如果两个操作数算术上相等则为 std::strong_ordering::equal
    • 如果第一操作数算术上小于第二个则为 std::strong_ordering::less
    • 否则为 std::strong_ordering::greater
  • 如果各操作数为浮点数类型,那么运算符产出 std::partial_ordering 类型的值:
    • 如果 a<ba < b 则为 std::partial_ordering::less
    • 如果 a>ba > b 则为 std::partial_ordering::greater
    • 如果 a=ba = b 则为 std::partial_ordering::equivalent
    • 否则为 std::partial_ordering::unordered(无序)。

范围 for 中的初始化语句和初始化器

开始支持 init-statement,可以在 for 循环的初始化部分声明变量。
人话:范围 for 循环语句支持初始化语句。
示例:
CPP
for(int i = 0; pair<int, int> j : Map)

日历功能

  • 初始化 年、月、日:
    CPP
    auto y1 = year {2019}; 
    auto y2 = 2019y; 
    
    auto m1 = month {9}; 
    auto m2 = September; 
    
    auto d1 = day {18}; 
    auto d2 = 18d;
    
  • 完整日期
    CPP
    year_mouth_day fdt1 {2019y, September, 18d}; 
    auto fdt2 = 2019y / September / 18d; 
    year_mouth_day fdt3 {Monday[3] / September / 2019};
    
    如果让刚入门的 OI 初学者知道会怎么样。

格式化库 (std::format)

头文件 <format>
示例:
CPP
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>:数学常数 ee
  • std::numbers::ln2_v<_Tp>ln2\ln 2
  • std::numbers::ln10_v<_Tp>ln10\ln 10
  • std::numbers::sqrt2_v<_Tp>2\sqrt{2}
  • std::numbers::sqrt3_v<_Tp>3\sqrt{3}

函数

  • midpoint()
    • midpoint(T a, T b)a+b2\frac{a + b}{2}aa 取整。
    • midpoint(T * a, T * b):若 aabb 分别指向同一数组对象 xxx[i]x[j],则返回指向 x[std::midpoint(i, j)]

C++ 23

if consteval

指在编译阶段可以可以进行条件编译,并根据结果选择可以编译或者不编译哪些代码块。
CPP
if consteval {} else {}
CPP
if !consteval {} else {}

多维下标运算符

大白话:重载数组下标。
CPP
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]] 属性允许开发者在代码中声明某些条件总是为真,帮助编译器进行更好的优化。
CPP
int divide(int a, int b)
{
	[[assume(b != 0)]];
	return a / b;
}

命名通用字符转义

'\N{WHITE SMILING FACE}' WHITE SMILING FACE 是 Unicode 字符的名字,对应的 Unicode 码点是 U+263A。

新容器:flat_mapflat_set

真正有用的东西来了!
性能优化的平面映射 (flat_map) 和集合 (flat_set) 容器。
使用连续的内存块存储元素,从而减少了内存分配和访问时间。
适合于频繁查找操作的场景。

运行时堆栈跟踪

头文件 <stacktrace>
CPP
std::stacktrace::current()
示例输出:
CPP
foo() at example.cpp:5
main() at example.cpp:10

printprintln

类似于 format()(C++ 20)。
printlnprint 多了一个换行符。

评论

8 条评论,欢迎与作者交流。

正在加载评论...