在 Internet 上,我们经常使用 32 位地址,我们将其序列化为字符串,例如 192.128.0.1。该字符串对应于整数地址 0xc0800001(十进制为 3229614081)。
您如何在 C++ 中有效地序列化,从整数到字符串?
现代 C++ 中最简单的代码可能如下所示:
std :: string output = std :: to_string (地址>> 24 ) ; 对于( int i = 2 ; i > = 0 ; i - - ) { 输出。追加( std :: to_string ( (地址>> ( i * 8 ) ) % 256 ) + “ 。 ” ) ; }
至少象征性地,它将重复创建附加到初始字符串的小字符串。
我们能做得更好吗?我们在 C++ (std::to_chars) 中有新函数,专门用于快速写入字符串缓冲区。所以我们可能会尝试分配一个缓冲区并使用缓冲区写入它。结果并不漂亮:
std ::字符串输出( 4 * 3 + 3 , '\0' ) ; // 只分配一个大字符串 字符*点=输出。数据( ) ; 字符* point_end =输出。数据( ) +输出。尺寸( ) ; point = std :: to_chars ( point , point_end , uint8_t ( address >> 24 ) ) 。指针; 对于( int i = 2 ; i > = 0 ; i - - ) { *点+ + = '.' ; point = std :: to_chars ( point , point_end , uint8_t ( address >> ( i * 8 ) ) ) 。指针; } 输出。 resize ( point-output.data ( ) ) ;
更丑陋的代码可能会更快。
我写了一个基准测试,我在其中重复创建字符串并将它们添加到容器中。
在使用 GCC 11 的 AMD Rome (Zen2) 处理器上,我得到以下数字。
漂亮的代码 | 80 纳秒/串 |
to_chars | 24 纳秒/串 |
那么大约快三倍?
与往常一样,您的结果会因您的系统和编译器而异。但是,我建议不要在性能关键代码中创建小字符串并将它们聚合在一起。
原文: https://lemire.me/blog/2023/02/01/serializing-ips-quickly-in-c/