跳到主要内容 C++23 常用特性详解 | 极客日志
C++
C++23 常用特性详解 C++23 的新特性,涵盖核心语言改进如 deducing this、constexpr 增强、if consteval,以及标准库更新包括 std::expected、扁平化容器、格式化输出等。文章还探讨了实际应用场景及主流编译器支持情况,为开发者提供迁移指南。
数字游民 发布于 2026/3/29 更新于 2026/4/17 7 浏览C++23 常用特性
一、核心语言特性
1.1 deducing this
1.1.1 简化 CRTP 模式
CRTP(Curiously Recurring Template Pattern)是一种常用设计模式,传统实现需要手动传递派生类类型:
template <typename Derived>
struct Base {
void {
<Derived*>( )-> ();
}
};
: Base<Derived> {
{ }
};
func
()
static_cast
this
impl
struct
Derived
void impl ()
C++23 通过 deducing this 自动推导派生类类型:
struct Base {
template <typename Self>
void func (this Self&& self) {
self.impl ();
}
};
struct Derived : Base {
void impl () {
std::cout << "Derived::impl" << std::endl;
}
};
1.1.2 成员函数模板推导 deducing this 允许成员函数根据 this 的类型(左值/右值)推导模板参数:
struct MyClass {
template <typename Self>
auto get (this Self&& self) {
if constexpr (std::is_lvalue_reference_v<Self>) {
return std::ref (self.data);
} else {
return std::move (self.data);
}
}
private :
std::string data = "hello" ;
};
1.2 constexpr 增强
1.2.1 constexpr for 循环 C++23 允许 for 循环在 constexpr 函数中使用,支持编译期迭代:
constexpr auto sum (std::initializer_list<int > list) {
int s = 0 ;
for (int x : list) {
s += x;
}
return s;
}
consteval int s = sum ({1 , 2 , 3 });
1.2.2 constexpr 动态内存管理优化 C++23 放松 constexpr 中动态内存的限制,允许 new/delete 在编译期更灵活使用:
constexpr std::vector<int > create_vector () {
std::vector<int > v;
v.reserve (3 );
v.push_back (1 );
v.push_back (2 );
v.push_back (3 );
return v;
}
constexpr auto vec = create_vector ();
1.3 if consteval
1.3.1 编译期与运行期分支 if consteval 判断当前上下文是否为编译期常量表达式,选择执行分支:
consteval int compile_time () {
return 42 ;
}
int run_time () {
return 42 ;
}
auto func (bool flag) {
if consteval {
return compile_time ();
} else {
return run_time ();
}
}
int main () {
int a = func (true );
int b = func (false );
return 0 ;
}
1.3.2 与 constexpr if 的区别
if consteval :判断上下文是否为编译期(如 consteval 函数内),分支在编译期确定。
constexpr if :判断条件是否为编译期常量,分支在编译期静态选择(未选中分支不生成代码)。
1.4 其他语言特性
1.4.1 static operator[] struct Config {
static std::unordered_map<std::string, int > settings;
static int operator [](const std::string& key) {
return settings[key];
}
};
std::unordered_map<std::string, int > Config::settings = {{"max_size" , 100 }};
int main () {
int max_size = Config["max_size" ];
return 0 ;
}
1.4.2 throw() noexcept 简化 throw() 等价于 noexcept(true),简化异常规范:
void func () throw () {}
void func () noexcept (true )
void func2 () noexcept {}
1.4.3 [[assume]] 属性 [[assume(condition)]] 提示编译器假设 condition 为真,优化代码(如删除冗余检查):
int div (int a, int b) {
[[assume (b != 0 )]];
return a / b;
}
二、标准库新增特性
2.1 std::expected
2.1.1 结果与错误的统一表示 std::expected<T, E> 表示操作结果(T)或错误(E),替代 std::optional+ 错误码:
#include <expected>
#include <string>
enum class Error { InvalidInput, OutOfRange };
std::expected<int , Error> parse_int (const std::string& s) {
if (s.empty ())
return std::unexpected (Error::InvalidInput);
return 42 ;
}
int main () {
auto res = parse_int ("42" );
if (res.has_value ()) {
int value = res.value ();
} else {
Error err = res.error ();
}
return 0 ;
}
2.1.2 and_then/or_else 链式调用 std::expected 支持链式调用,处理成功或失败的后续逻辑:
auto res = parse_int ("42" )
.and_then ([](int x) {
return x * 2 ;
})
.or_else ([](Error e) {
return std::unexpected (e);
});
2.2 扁平化容器(flat_map/flat_set)
2.2.1 内部结构与性能对比 std::flat_map/std::flat_set 内部用 std::vector 存储键值对,排序后通过二分查找访问:
优点 :内存连续,缓存友好,遍历速度快于 std::map。
缺点 :插入/删除需要移动元素,性能较差。
#include <flat_map>
#include <map>
#include <chrono>
int main () {
std::flat_map<int , int > fm;
std::map<int , int > m;
return 0 ;
}
2.2.2 适用场景
遍历密集型场景 :如日志分析、统计报表。
内存受限环境 :连续存储减少内存碎片。
2.3 std::print/std::println
2.3.1 格式化输出到标准流 std::print/std::println 直接格式化输出到 stdout,简化打印代码:
#include <print>
#include <string>
int main () {
std::print ("Hello, {}!\n" , "World" );
std::println ("Hello, {}!" , "World" );
return 0 ;
}
2.3.2 与 std::format 的配合 std::print 内部使用 std::format 的格式化逻辑,支持相同的格式规范:
std::println ("PI: {:.2f}" , 3.14159 );
2.4 ranges::to
2.4.3 范围转换为容器 ranges::to<C> 将范围转换为容器 C,简化范围到容器的转换:
#include <ranges>
#include <vector>
#include <views>
int main () {
auto view = std::views::iota (1 , 6 );
std::vector<int > vec = view | std::ranges::to <std::vector>();
return 0 ;
}
2.5 其他标准库特性
2.5.1 std::expected
2.5.2 std::byteswap #include <bit>
int main () {
uint16_t x = 0x1234 ;
uint16_t y = std::byteswap (x);
return 0 ;
}
2.5.3 std::stacktrace #include <stacktrace>
#include <iostream>
void func () {
auto st = std::stacktrace::current ();
std::cout << st << std::endl;
}
int main () {
func ();
return 0 ;
}
三、C++23 特性应用场景
3.1 deducing this 简化多态设计 使用 deducing this 实现静态多态,避免 CRTP 的繁琐类型传递:
struct Drawable {
template <typename Self>
void draw (this Self&& self) {
self.draw_impl ();
}
};
struct Circle : Drawable {
void draw_impl () {
std::cout << "Circle" << std::endl;
}
};
int main () {
Circle c;
c.draw ();
return 0 ;
}
3.2 std::expected 统一错误处理 std::expected<Response, NetworkError> fetch_data (const std::string& url) {
if (success)
return Response{...};
else
return std::unexpected (NetworkError::Timeout);
}
3.3 flat_map 优化遍历性能 游戏实体组件系统中,使用 flat_map 存储组件,加快遍历速度:
std::flat_map<EntityID, TransformComponent> transforms;
std::flat_map<EntityID, RenderComponent> renders;
for (auto & [id, transform] : transforms) {
auto it = renders.find (id);
if (it != renders.end ()) {
render (transform, it->second);
}
}
四、编译器支持与迁移
4.1 主流编译器支持情况
GCC :13+ 支持部分 C++23 特性(如 std::expected、flat_map)。
Clang :16+ 支持部分特性。
MSVC :Visual Studio 2022 17.5+ 支持部分特性。
4.2 从 C++20 迁移到 C++23
渐进式迁移 :优先使用稳定特性(如 std::print、flat_map)。
兼容性 :C++23 特性大多向下兼容,可混合使用 C++20 代码。
工具链更新 :确保编译器版本支持所需特性,启用 -std=c++23 编译选项。
微信扫一扫,关注极客日志 微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
相关免费在线工具 Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
Markdown转HTML 将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
HTML转Markdown 将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
JSON 压缩 通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online
JSON美化和格式化 将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online