Sim*_*mog 4 c++ stdstring c++20 std-span
我正在使用一个 C 库,它使用各种固定大小的unsigned char数组,不带空终止符作为字符串。
我已经将它们转换为std::string使用以下函数:
auto uchar_to_stdstring(const unsigned char* input_array, int width) -> std::string {
std::string temp_string(reinterpret_cast<const char*>(input_array), width);
temp_string.erase(temp_string.find_last_not_of(' ') + 1);
return temp_string;
}
Run Code Online (Sandbox Code Playgroud)
除了使用reinterpret_cast、需要传递数组大小以及我将数组衰减为指针之外,它工作得很好。我试图通过使用 来避免所有这些问题std::span。
使用的函数std::span如下所示:
auto ucharspan_to_stdstring(const std::span<unsigned char>& input_array) -> std::string {
std::stringstream temp_ss;
for (const auto& input_arr_char : input_array) {
temp_ss << input_arr_char;
}
return temp_ss.str();
}
Run Code Online (Sandbox Code Playgroud)
该函数运行良好,使其他一切变得更简单,而无需跟踪 C 数组的大小。但是,通过一些基准测试(使用nanobench )进一步挖掘表明,新函数比经典方法慢很多倍reinterpret_cast。我的假设是基于 - 的函数for中的循环std::span是这里效率低下的。
我的问题:是否有更有效的方法将固定大小的无符号字符 C 数组从std::span变量转换为std::string?
编辑:
gcc基准测试(-O3 -DNDEBUG -std=gnu++20、nanobench、minEpochIterations=54552558、warmup=100、doNotOptimizeAway)
| 相对的 | ns/操作 | 操作/秒 | 呃% | 插入/操作 | 胸罩/手术衣 | 错过% | 全部的 | uchar[] 到 std::string |
|---|---|---|---|---|---|---|---|---|
| 100.0% | 5.39 | 185,410,438.12 | 0.3% | 80.00 | 20:00 | 0.0% | 3.56 | uchar |
| 2.1% | 253.06 | 3,951,678.30 | 0.6% | 4,445.00 | 768.00 | 0.0% | 167.74 | ucharspan |
| 1,244.0% | 0.43 | 2,306,562,499.69 | 0.2% | 9.00 | 1.00 | 0.0% | 0.29 | ucharspan_barry |
| 72.8% | 7.41 | 134,914,127.56 | 1.3% | 99.00 | 22:00 | 0.0% | 4.89 | uchar_bsv |
clang基准测试(-O3 -DNDEBUG -std=gnu++20、nanobench、minEpochIterations=54552558、warmup=100、doNotOptimizeAway)
| 相对的 | ns/操作 | 操作/秒 | 呃% | 插入/操作 | 胸罩/手术衣 | 错过% | 全部的 | uchar[] 到 std::string |
|---|---|---|---|---|---|---|---|---|
| 100.0% | 2.13 | 468,495,014.11 | 0.2% | 14:00 | 1.00 | 0.0% | 1.42 | uchar |
| 0.8% | 251.74 | 3,972,418.54 | 0.2% | 4,477.00 | 767.00 | 0.0% | 166.30 | ucharspan |
| 144.4% | 1.48 | 676,329,668.07 | 0.1% | 7点 | 0.00 | 95.8% | 0.98 | ucharspan_barry |
| 34.5% | 6.19 | 161,592,563.70 | 0.1% | 80.00 | 24:00 | 0.0% | 4.08 | uchar_bsv |
(uchar_bsv在基准测试中与 相同ucharspan_barry,但用std::basic_string_view<unsigned char const>参数代替std::span<unsigned char const>
你要:
auto ucharspan_to_stdstring(std::span<unsigned char const> input_array) -> std::string {
return std::string(input_array.begin(), input_array.end());
}
Run Code Online (Sandbox Code Playgroud)
string与其他标准库容器一样,可以从适当的迭代器对构造 - 这就是这样的一对。由于这些是随机访问迭代器,因此这将执行一次分配等。
请注意,我从 更改span<T> const&为span<T const>,有两个原因。首先,您不会改变跨度的内容,因此内部类型需要const...类似于您采用 aT const*而不是 a 的方式T*。其次,您应该span按值获取 s,因为复制它们的成本很低(除非您非常特别需要跨度的标识,但这里不需要)。
最好这样做,reinterpret_cast以便您可以使用(char const*, size_t)构造函数 - 这可以确保memcpy最终的写入是单一的。但你必须把握好时机,看看是否值得。
| 归档时间: |
|
| 查看次数: |
3941 次 |
| 最近记录: |