string不是std的成员_std::format for C++20简介

C语言格式化字符串的解决方案printf系列函数(printf/sprintf/fprintf/snprintf等)性能较高,但是使用%s的时候容易崩溃,虽然现在编译器都可以给出警告,但是其它的毛病比如说浮点数格式化精度丢失(本文后面会举例)依然是不得不面对的问题。

C++相对C的最大区别之一就是尽可能地追求typesafe,所以C++从一开始就在寻找替代printf系列函数的解决方案,于是从一开始就有了各种各样的ostream。typesafe是做到了,但是性能低下。

第三方库也在努力,比如说boost很早就引入了boost::format,只可惜它也有严重的性能问题。直到一个名字叫fmtlib的第三方库的出现,这个现状才得以改变。

fmtlib的部分功能被加入到了C++20,它就是std::format。它的速度比printf系列函数平均快出35%,有时候甚至更多(对于浮点数,std::format甚至比snprintf快出10倍以上)。

0fd6f8065310f9949c4ffb3eb3db4a63.png

除此以外,它还有更多的优点。下面随便列举几个。

解决浮点数精度丢失问题

直接来看例子吧

double pi = 3.14159265358979;
printf("%fn", pi); // 输出3.141593,后面的被四舍五入了
cout<<format("{}n", pi); // format,输出完整的3.14159265358979

// 与snprintf函数对应的是format_to_n
char buff[50];
sprintf(buff, "%f", pi);
cout<<buff<<"n"; // 与printf一样,输出3.141593
format_to_n(buff, sizeof(buff), "{}", pi);
cout<<buff<<"n"; // 3.14159265358979

与STL容器完美结合

vector<char> v;
format_to(std::back_inserter(v), "{}", "1999"); // 输出到iterator
// now v is {'1', '9', '9', '9'}
assert(v[3] == '9');

可提前算出format之后所需内存空间

format之前可以调用formated_size函数提前算出本次format所需要的内存空间

 auto size = std::formatted_size("{}", 42); // size == 2
 std::vector<char> buf(size); // 根据上面返回的size,将内存分配好
 std::format_to(buf.data(), "{}", 42);

支持自定义的类型扩展

通过模板特化自定义struct std::formatter<YourType>,就可以让YourType类型支持std::format。其主要就是定义两个成员函数:parse和format,这里不举例了。像std::chrono里面常见的日期时间类型相关的std::formatter都已经放进标准库了,不需要自己写了。

支持编译时的parse

上面提到,自定义类型的format需要提供两个函数:parse和format,其中parse可以通过constexpr指定为在编译期间运行,大大提升性能。

只不过第二个函数format还不支持编译时运行,但是以后某个版本可能会支持。

format功能其实是非常重要的,因为C++追求高效,所以做一个通用的且大家都看得上的format库一直很难,现在终于有了。

当然,有了format,有时候还需要parse,就是从一个已经format的字符串反向解析出各个变量。这个已经有相关的标准了,或许未来会成为std::parse,但即使只是作为第三方库出现,只要和format的格式配套起来,也会有很用。

std::string key;
int value;
fmt::scan("answer = 42", "{} = {}", key, value);
assert(key=="answer");
assert(value==42);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值