前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >C++性能优化神器:它 比 std::stoi 快 3 倍!

C++性能优化神器:它 比 std::stoi 快 3 倍!

作者头像
程序员的园
发布于 2025-04-01 06:24:21
发布于 2025-04-01 06:24:21
11000
代码可运行
举报
运行总次数:0
代码可运行

1. 背景

我最近在项目中遇到一个需求——针对同一个类型的接口,需要支持传入多种数据类型,大概形式如下,

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void UpdateValue(const char* value_name,int value);
void UpdateValue(const char* value_name,double value);
void UpdateValue(const char* value_name,const char* value);

如果是C++接口,可以用重载用模板,但是我需要提供C接口,这些特性都用不了。虽然可以采用如下的方案:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void UpdateIntValue(const char* value_name,int value);
void UpdateDoubleValue(const char* value_name,double value);
void UpdateCharValue(const char* value_name,const char* value);

但是这样的话,每次有新的类型,都需要增加新的接口,每次增加新的接口,都意味着使用库的铜须需要重新编译、集成,这套方案显然是不成熟的。 通过思考发现,我可以通过value_name知晓value的类型,所以可以考虑如下的方案:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void UpdateValue(const char* value_name, const char* value);

这样提供的接口是稳定的,不会因为类型增加而改变。但是这样又引入了一个新的问题,就是如何将char*转换为对应的类型,比如int、double等。

通常情况下,我们会使用std::stoistd::stof等函数,但是这些函数存在一些问题:

  • 性能问题:std::stoi() 和 std::stof() 需要将输入转换为 std::string,这可能导致额外的堆分配和数据拷贝,从而降低性能。
  • **依赖 std::locale**:许多标准转换函数受 std::locale 影响,可能导致额外的性能开销。
  • 不灵活std::stoi() 只能处理 std::string,而 std::strtol() / std::strtof() 需要 C 风格字符串,使用起来不够现代化。

对于依赖和不灵活,我到可以退而求其次,但是性能一直是我特别关注的。后来我发现了charconv,它是一个用于字符数组与数值类型之间转换的库,可以高效地进行数值解析和格式化。

当前可查的 std::from_chars()std::stoi() / std::stof() 的性能对比结果如下:

方法

解析整数 (100 万次)

解析浮点数 (100 万次)

std::stoi

120 ms

-

std::from_chars

35 ms

90 ms (C++20)

std::strtol

100 ms

-

std::strtod

-

180 ms

从数据来看,std::from_chars() 解析 整数比 std::stoi() 快 3~4 倍,解析 浮点数比 std::strtod() 快 2 倍,这对性能敏感的应用来说是一个巨大的提升。

2. charconv

<charconv>C++17 引入,提供 std::to_chars()std::from_chars(),用于在 数值类型和字符数组 之间进行高效转换。 其使用非常简单,如下仅以整数为例,其余类型雷同。

整数转字符串 (to_chars)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <charconv>
#include <iostream>
#include <array>

int main() {
    std::array<char, 20> buffer; // 预分配足够大的缓冲区
    int value = 12345;
    
    auto [ptr, ec] = std::to_chars(buffer.data(), buffer.data() + buffer.size(), value);
    
    if (ec == std::errc{}) {
        std::cout << "Converted: " << std::string(buffer.data(), ptr) << std::endl;
    } else {
        std::cerr << "Conversion failed" << std::endl;
    }
}

字符串转整数 (from_chars)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <charconv>
#include <iostream>

int main() {
    constchar* str = "12345";
    int value;
    
    auto [ptr, ec] = std::from_chars(str, str + std::strlen(str), value);
    
    if (ec == std::errc{}) {
        std::cout << "Parsed value: " << value << std::endl;
    } else {
        std::cerr << "Parsing failed" << std::endl;
    }
}

3. 实战建议

虽然 charconv 性能强大,但在使用时需要注意以下几点:

  • 负数解析: std::from_chars() 解析数字时,直到C++20后才支持解析负数,如果项目中不能使用C++20时,需要手动处理:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const char* str = "-123";
int value;

if (*str == '-') {
    auto [ptr, ec] = std::from_chars(str + 1, str + std::strlen(str), value);
    value = -value; // 手动处理负号
}
  • 需要确保缓冲区足够大:使用 std::to_chars() 时,需要保证 char 数组大小足够,否则可能会转换失败。

4. 总结

std::charconv 提供了高效数值转换方法,不仅可以显著提高性能,还避免了 std:locale 影响。但是使用时还需要注意如上的实战建议。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-03-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员的园 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
C++17 中的 std::to_chars 和 std::from_chars:高效且安全的字符串转换工具
在现代 C++ 开发中,字符串与数值之间的转换是一个常见的需求,尤其是在处理输入输出、数据解析和格式化时。C++17 引入了 std::to_chars 和 std::from_chars,这两个函数为开发者提供了高效、安全且灵活的字符串转换工具。
码事漫谈
2025/02/20
2012
C++17 中的 std::to_chars 和 std::from_chars:高效且安全的字符串转换工具
【C++奇迹之旅】:字符串转换成数字&&将数字转换成字符串&&大全
在 C++ 里,把字符串转换成数字有多种方式,下面针对不同的数据类型和使用场景详细介绍具体
学习起来吧
2025/03/02
2511
C++ 中文周刊 2024-10-22 第169期
编译器信息最新动态推荐关注hellogcc公众号 本周更新 2024-10-16 第276期
王很水
2024/10/22
840
C++ 中文周刊 2024-10-22 第169期
C++23 对部分特性的 constexpr 支持
在 C++ 编程中,constexpr 关键字自 C++11 引入以来,便致力于让更多的计算在编译时完成,以此提升程序的性能与效率。C++23 进一步拓展了 constexpr 的应用范畴,为 std::bitset、std::unique\_ptr、std::type\_info::operator==、部分 <cmath> 函数以及 std::to\_chars 和 std::from\_chars 的整型重载等带来了 constexpr 支持。下面将详细介绍这些特性在 C++23 中的 constexpr 支持情况。
码事漫谈
2025/05/25
950
C++23 对部分特性的 constexpr 支持
c++中的std::stod, stCPP程序说明std::stod():stof, std::stold
如果未执行转换,则会引发invalid_argument异常。如果读取的值超出双精度的可表示值范围,则会引发out_of_range异常。无效的 idx 会导致未定义的行为。
鲸落c
2022/12/14
3.1K0
【C++篇】像解谜一样转换字符串:stoi 带你走向整数的世界
stoi 是 C++11 引入的一个标准库函数,常用于将字符串转换为整数。它的全称是 "string to integer"。
熬夜学编程的小王
2024/11/25
6930
C/C++数字与字符串互相转换
在C/C++程序中,会需要把数字与字符串做出互相转换的操作,用于实现程序想要的效果。下面将介绍多种方法实现数字与字符串互相转换。
摆烂小白敲代码
2024/09/23
2640
C/C++数字与字符串互相转换
C++23中std::optional和std::expected的单子式操作
在C++编程中,错误处理和可选值的管理是非常重要的部分。C++17引入了std::optional,它提供了一种新的标准方式来表达可能缺失的值。而C++23在此基础上,不仅对std::optional进行了扩展,还引入了std::expected,并且为它们都提供了受函数式编程启发的新接口,特别是单子式操作(transform、or_else与and_then),这些操作可以简化代码并提高代码的可读性和可维护性。
码事漫谈
2025/05/03
830
C++23中std::optional和std::expected的单子式操作
c++17好用的新特性总结
最近很火的鸿蒙系统框架代码,很多就是基于c++做的底层、运行时和应用框架封装。c++11后续又有11,14,17,20等众多新版本。哪个是主流?截至目前来说,c++17应该是新项目的首选。C++14在11的基础上查缺补漏,并未加入许多新特性,而C++17作为C++11后的第一个大版本,标志着现代C++逐渐走向成熟。
杨永贞
2022/05/25
3.6K0
c++17好用的新特性总结
【备忘录】c++ 整形浮点字符串 类型转换
一、C风格字符串 1.<stdlib.h>中的转换函数  atoi atol atoll itoa ltoa ultoa lltoa atof ecvt fcvt gcvt strtol strtoul strtoll strtod 2. sprintf  sscanf (功能更强大) 二、std::string 1.标准库转换函数  (using namespace std;) to_string stoi stol stoul stoll stoul stof stod stold 2.字符串流
ApacheCN_飞龙
2019/02/15
7370
C++数值类型与string的相互转换
std命令空间下有一个C++标准库函数std::to_string(),可用于将数值类型转换为string。使用时需要include头文件<string>。
恋喵大鲤鱼
2018/08/03
9.9K0
【C++】字符转整形的多种方法
在C++中,字符与数字有着直接的关联。每个字符在计算机中都有一个对应的整数值,这个值通常被称为字符的ASCII值(对于ASCII字符集)。例如,字符 '0' 的ASCII值为48,字符 '1' 的ASCII值为49,依此类推。因此,字符 '5' 可以通过减去字符 '0' 来得到整数 5。这种方式虽然简单,但是并不适用于复杂的字符串转换问题。
CSDN-Z
2025/02/05
5550
【C++】字符转整形的多种方法
为什么需要模板?—— C++ 泛型编程的核心价值
在 Windows 客户端开发中,我们经常需要处理多种数据类型:从 GUI 控件的泛型容器,到系统 API 的跨类型封装,再到高性能算法的类型抽象。本章将深入探讨 C++ 模板如何通过泛型编程解决这些问题,并通过 Windows 注册表操作等实战案例,展示模板在真实场景中的强大能力。
lealc
2025/02/11
3200
为什么需要模板?—— C++ 泛型编程的核心价值
C++ 中文周刊 第93期
编译器信息最新动态推荐关注hellogcc公众号 2022-12-14 第180期
王很水
2022/12/31
4370
C++ 动态新闻推送 第38期
之前提到过,std::string的resize是会走一遍构造的,这对于后续操作来说无疑是多余的动作,所以编译器也开洞了一个resize_uninit接口,当然这不是标准的一部分
王很水
2021/11/22
6710
6.1 C/C++ 封装字符串操作
C/C++语言是一种通用的编程语言,具有高效、灵活和可移植等特点。C语言主要用于系统编程,如操作系统、编译器、数据库等;C语言是C语言的扩展,增加了面向对象编程的特性,适用于大型软件系统、图形用户界面、嵌入式系统等。C/C++语言具有很高的效率和控制能力,但也需要开发人员自行管理内存等底层资源,对于初学者来说可能会有一定的难度。
王 瑞
2023/10/10
4690
6.1 C/C++ 封装字符串操作
重温 C/C++ 笔记
编码风格:http://openresty.org/cn/c-coding-style-guide.html
张拭心 shixinzhang
2021/12/31
1.4K0
重温 C/C++ 笔记
C/C++语言字符串操作总结大全(超详细)
strpbrk(p, p1) 以目标字符串的所有字符作为集合,在当前字符串查找该集合的任一元素
用户7886150
2021/02/08
9320
[C] C中的字符串处理函数
函数名: strcpy 功 能: 拷贝一个字符串到另一个 用 法: char *stpcpy(char *destin, char *source); 程序例:
轻舞飞扬SR
2021/02/24
2.1K0
【Linux网络编程】Socket编程--UDP(第一弹):实现客户端和服务器互相发送消息
任何一个UDP服务通信中,都需要有一个int sockfd的文件描述符,按照系统编程中所说,这里打印出来的文件描述符应该是3,因为0,1,2已经被占用了。
南桥
2024/10/20
2570
【Linux网络编程】Socket编程--UDP(第一弹):实现客户端和服务器互相发送消息
相关推荐
C++17 中的 std::to_chars 和 std::from_chars:高效且安全的字符串转换工具
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验