"Hello World" in C++23
随着Modules和Formatting Library顺利进入C++20,标准库Modules和Formatted output进入C++23不过是水到渠成。
这种先引入再扩展的标准发展方式在C++中已不稀奇,这两个新特性自然也就成为C++23中主要的特性之二。
C++2a之后,Ranges, Modules, Concepts, Coroutines, 以及将要引入的新特性,都将会在一定程度上改变我们以往的编译方式。
而这一切的基础,都在于新特性是否足够完善。三年一小步,六年一大步,此之谓也。
由经典的入门代码,可以看到,C++俨然成为了一门新语言。
越现代,越强大,这种使用方式以后可能会越发流行。因为不论是性能还是可用性,新特性都更具有优势。
首先是标准库Modules。
Modules具有缩短编译时间、解决重复替换、导入顺序无关,以及无需分离接口与实现等等优势,若标准库迟迟不提供Modules版本,反而会阻碍Modules的发展。
因此,标准库Modules的优先级并不低,进标准也是顺理成章。
接着是Formatted output。
用过fmt库的都清楚,这可是个好东西,或者可以说是cout终结者。
标准cout是个糟糕的设计。第一,其可用性差,基本没有格式化能力;第二,它会多次调用格式化I/O函数;第三,性能低,默认会同步标准C的流;第四,它的内容由参数交替组成,在多线程时,结果将会错乱显示;第五,它的二进制占用空间较大。
格式化输出的目标是要满足:可用性、支持Unicode编码、良好的性能,与较小的二进制占用空间。
为了不影响现有代码,该特性专门加了一个新的头文件<print>,包含两个主要函数。
#include <print>
int main() {
const char* world = "world";
std::print("Hello {}", world); // doesn't print a newline
std::println("Hello {}", world); // print a newline
}
其中std::print的格式化语法同格式化库,可以参考Using C++20 Formatting Library。而std::println则会在输出的内容之后添加一个换行,这是对比了C/Java/Rust/Go/C#/.Net等等语言之后作出的选择。
关于性能,可能看看作者的对比结果:
----------------------------------------------------------
Benchmark Time CPU Iterations
----------------------------------------------------------
printf 87.0 ns 86.9 ns 7834009
ostream 255 ns 255 ns 2746434
print 78.4 ns 78.3 ns 9095989
print_cout 89.4 ns 89.4 ns 7702973
print_cout_sync 91.5 ns 91.4 ns 7903889
可以看到,printf与print几乎要比cout快三倍,print默认会打印到stdout。当打印到cout并同步标准C的流时(print_cout_sync),print大概要快14%;当不同步标准C的流时(print_cout),依旧要快不少。
此外,使用std::print可以直接格式化输出Ranges,这可以省去大量的循环。
本文是一篇评价性的文章,并不讨论使用细节。
其实这两个新特性的内容并不算多,Modules大家可能会相对陌生,但格式化库已不是太新的东西了,平时习惯使用fmt库的对格式化输出也不会感到新奇,毕竟print在fmt库中已实现并使用了近6年。
总而言之,目前来看只要这些特性够完善,没什么大Bug,在未来将会改变一些我们一直以来养成的编程习惯,随之带来的是性能与可用性的提高,且有些现有问题将成为过去式。