콘텐츠로 이동

std::from_chars / to_chars 고성능 문자열 변환

std::from_charsstd::to_chars는 C++17에서 도입된 저수준 고성능 문자열 변환 함수입니다. 로케일 독립적이고 동적 메모리 할당이 없으며, 예외도 던지지 않아 파서, 직렬화, 로깅 등 성능 민감한 경로에 적합합니다.


#include <charconv>
#include <string_view>
#include <cassert>
int main()
{
std::string_view sv = "12345";
int result{};
auto [ptr, ec] = std::from_chars(sv.data(), sv.data() + sv.size(), result);
if (ec == std::errc{})
// 성공: result == 12345, ptr == sv.end()
assert(result == 12345);
else if (ec == std::errc::invalid_argument)
// 숫자가 아닌 입력
;
else if (ec == std::errc::result_out_of_range)
// 오버플로
;
}

#include <charconv>
#include <array>
#include <string_view>
int main()
{
int value = 42;
std::array<char, 20> buf;
auto [ptr, ec] = std::to_chars(buf.data(), buf.data() + buf.size(), value);
if (ec == std::errc{})
{
std::string_view sv(buf.data(), ptr);
// sv == "42"
}
}

#include <charconv>
#include <array>
int parse_hex(std::string_view s)
{
int result{};
std::from_chars(s.data(), s.data() + s.size(), result, 16);
return result;
}
// "ff" → 255, "1A" → 26
std::string to_hex(int v)
{
std::array<char, 20> buf;
auto [ptr, ec] = std::to_chars(buf.data(), buf.data() + buf.size(), v, 16);
return std::string(buf.data(), ptr);
}
// 255 → "ff"

#include <charconv>
#include <array>
double parse_double(std::string_view s)
{
double result{};
std::from_chars(s.data(), s.data() + s.size(), result);
return result;
}
// 부동소수점 출력 형식 제어
std::string format_double(double v)
{
std::array<char, 32> buf;
// 고정 소수점 6자리
auto [ptr, ec] = std::to_chars(
buf.data(), buf.data() + buf.size(),
v,
std::chars_format::fixed, 6);
return std::string(buf.data(), ptr);
}
// 3.14159265 → "3.141593"

std::chars_format 옵션:

  • fixed — 고정 소수점
  • scientific — 과학적 표기 (1.23e+04)
  • hex — 16진수 부동소수점
  • general — 더 짧은 형식 자동 선택

함수로케일 의존예외동적 할당상대 속도
atoi기준
stoi느림
sscanf느림
from_chars빠름 (~3×)

#include <charconv>
#include <string_view>
#include <vector>
std::vector<int> parse_csv_ints(std::string_view line)
{
std::vector<int> result;
const char* ptr = line.data();
const char* end = ptr + line.size();
while (ptr < end)
{
int val{};
auto [next, ec] = std::from_chars(ptr, end, val);
if (ec == std::errc{})
result.push_back(val);
ptr = next;
while (ptr < end && (*ptr == ',' || *ptr == ' '))
++ptr; // 구분자 건너뛰기
}
return result;
}
// "1, 2, 3, 42" → {1, 2, 3, 42}

#include <charconv>
#include <optional>
#include <string_view>
template<typename T>
std::optional<T> parse(std::string_view s) noexcept
{
T result{};
auto [ptr, ec] = std::from_chars(s.data(), s.data() + s.size(), result);
if (ec == std::errc{} && ptr == s.data() + s.size())
return result;
return std::nullopt;
}
auto v = parse<int>("123"); // optional{123}
auto bad = parse<int>("12x"); // nullopt (전체 소비 안됨)

from_chars/to_chars는 파서, 직렬화, 로깅처럼 많은 양의 숫자 변환이 필요한 경로에서 stoi/to_string의 로케일 오버헤드와 예외 비용을 제거합니다. std::errc로 오류를 값으로 처리하고 동적 할당이 전혀 없으므로 임베디드나 게임 서버 같은 성능 민감한 환경에서도 안전하게 사용할 수 있습니다.