admin 管理员组文章数量: 1184232
本文记录C++20新特性之std::format和span。
第二章 C++20标准库特性
2.1 std::format
在C++20之前,文本格式化主要依赖于 C 风格的 printf函数或 C++ 的 iostream 流操作。printf 缺乏类型安全且难以扩展,而 iostream 虽然类型安全但语法繁琐且性能不高。
C++20引入了库,提供了一个类型安全、高效且语法类似于 Python 字符串格式化的现代解决方案。
2.1.1 基本语法
std::format 的核心思想是使用花括号 {} 作为占位符。它返回一个 std::string。
示例1:{}用法说明。
voidtest(){
std::string name ="wangandy";int id =330;
std::string message = std::format("我叫 {}!,id 为 {}", name, id);
std::cout << message << endl;// 我叫 wangandy!,id 为 330}需要注意的是,{}中不能加空格等不符合语法的字符。
2.1.2 位置参数
可以通过在花括号中指定索引来控制参数的参入顺序。
示例2:下面的示例中在{}中指定参数顺序。
voidtest(){
std::string name ="wangandy";int id =330;
std::string message = std::format("我叫 {0}!,id 为 {1}", name, id);
std::cout << message << endl;// 我叫 wangandy!,id 为 330
std::string message2 = std::format("我叫 {1}!,id 为 {0}", name, id);
std::cout << message2 << endl;// 我叫 330!,id 为 wangandy}2.1.3 格式说明符
std::format支持丰富的格式化选项,语法如下:
{:[fill][align][sign][#][0][width][.precision][type]}
{} : 替换字符的标志,其中包含要格式化的参数索引和格式说明。
“:” : 分割符,用于分隔参数索引和格式说明。
voidtest(){// 1. width 和 align (宽度和对齐)// >10 表示右对齐,总宽度为10
std::cout << std::format("右对齐: |{:>10}|","hi")<< std::endl;// 输出: 右对齐: | hi|// 2. fill 和 align (填充和对齐)// *^10 表示居中对齐,总宽度为10,用*填充
std::cout << std::format("居中填充: |{:*^10}|","hi")<< std::endl;// 居中填充: |****hi****|// 3. sign (符号)
std::cout << std::format("显示符号: {:+} 和 {:+}",12,-12)<< std::endl;// 输出: 显示符号: +12 和 -12
std::cout << std::format("空格符号: {:} 和 {:} ",12,-12)<< std::endl;// 输出: 空格符号: 12 和 -12// 4. # (替代形式) 和 type (类型)
std::cout << std::format("十六进制: {0:x}, {0:#x}, {0:#X}",12)<< std::endl;// 输出: 十六进制: c, 0xc, 0XC
std::cout << std::format("二进制: {0:b}, {0:#b}",12)<< std::endl;// 输出: 二进制: 1100, 0b1100// 5. 0 (零填充)
std::cout << std::format("零填充: {:08d}",123)<< std::endl;// 输出: 零填充: 00000123// 6. .precision (精度)
std::cout << std::format("浮点数精度: {:.2f}",3.14159)<< std::endl;// 输出: 浮点数精度: 3.14
std::cout << std::format("字符串精度: {:.5s}","hello world")<< std::endl;// 输出: 字符串精度: hello// 7. 综合示例double temperature =25.6789;
std::cout << std::format("温度: |{:+010.2f}|", temperature)<< std::endl;// 输出: 温度: |+000025.68|// 解释:// + : 显示正号// 0 : 使用0填充// 10: 总宽度为10// .2: 小数点后保留2位// f : 浮点数类型}2.1.4 总结
性能:format的性能优于iostream,在某些情况下超过 printf.
语法:format结合了python风格的易用性和C++的高性能,是现代C++开发中处理字符串的首选工具。
2.2 std::span
在C++20之前,我们需要连续内存块保存数据时,通常使用vector或者C风格的数组。编写一个函数处理这个数组时,在函数中传递这个数组,如下:
// 方式 A: 只能接受 vector,不能接受原生数组或 std::arrayvoidprint(const std::vector<int>& v);// 方式 B: C 风格 传递指针 和 长度voidprint(constint* ptr, size_t size);C++20中,可以直接使用span输出,它充当了不同容器类型之间的通用接口。
voidprint(std::span<int> s){for(int x : s){
std::cout << x <<" ";}
std::cout << std::endl;}voidtest(){int arr[]={1,2,3};
vector<int> vec ={4,5,6,7};
std::array<int,3> stdarr ={8,9,10};print(arr);// 从原生数组创建 spanprint(vec);// 从 vector 创建 spanprint(stdarr);// 从 std::array 创建 span}2.2.1 span原理
std::span 有两个模板参数:
std::span<T, Extent>
std::dynamic_extent (默认): 长度在运行时确定。这是最常用的形式,如 std::span。
静态长度: 长度在编译时确定。如 std::span<int, 5>。这允许编译器进行更激进的优化,并强制长度检查。
2.2.2 切片功能
std::span 最强大的功能之一是能够轻松创建子视图,而无需复制数据。这类似于 Python 的切片或 Go 的 slice。
voidtest(){
std::vector<int> data ={0,1,2,3,4,5,6,7,8,9};
std::span<int> s = data;// 获取前3个元素
std::span<int> first3 = s.first<3>();for(int x : first3){
std::cout << x <<" ";}
cout << endl;// 获取后3个元素
std::span<int> last3 = s.last<3>();for(int x : last3){
std::cout << x <<" ";}
cout << endl;// 获取从索引2开始的4个元素
std::span<int> subspan = s.subspan(2,4);for(int x : subspan){
std::cout << x <<" ";}
cout << endl;/*
0 1 2
7 8 9
2 3 4 5
*/}2.2.3 读取字节
std::as_bytes 和 std::as_writable_bytes 可以将任何 span 转换为字节视图(std::span),这在序列化或网络编程中非常有用。
voidsend_data(std::span<const std::byte> buffer){// 发送 buffer.size() 字节...}intmain(){double values[]={1.1,2.2};// 自动将 double 数组视为字节序列send_data(std::as_bytes(std::span(values)));}2.2.4 悬空引用
因为 std::span 不拥有内存,所以必须确保 span 的生命周期不超过它指向的数据的生命周期。
std::span<int>get_dangling(){
std::vector<int> v ={1,2,3};return v;// 错误方式,v 在函数结束时被销毁,返回的 span 指向无效内存。}2.2.5 span总结
span优点:零拷贝,统一接口(连续内存都可以使用span处理),类型安全,支持切片。
需要注意的是,使用span时,避免悬空引用。
版权声明:本文标题:C++20玩转新功能:_std::format与span,代码优化不再难! 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.roclinux.cn/p/1773653839a3564425.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论