Разница между std::stoi+std::to_string и std::from_chars+std::to_chars
#опытным
В C++ есть два основных подхода к конвертации чисел в строки и обратно:
Старомодный — std::stoi, std::to_string (C++11)
Модномолодежный — std::from_chars, std::to_chars (C++17)
В чем принципиальная разница между ними и когда какой подход использовать? Сегодня мы широкими мазками ответим на эти вопросы.
Особенности старомодного подхода:
👉🏿 Основное - это исключения. Все нештатные ситуации обрабатываются с их помощью, что ведет к неким накладным расходам.
👉🏿 Работа в высокоуровневом ООП стиле. Используются классы и возвращаются классы, без всяких сырых буферов.
👉🏿 Нет контроля над парсингом. Нет возможности задать формат, основание системы счисления или точность. Но для большинства кейсов это и не нужно.
👉🏿 Поддержка локалей. Грубо говоря, это механизм для учёта региональных особенностей представления данных. То есть std::stoi, std::to_string реализованы с учетом возможности спецификации локалей и соотвественно изменения результатов конвертации. С локалями возможна такая штука:
// В США (локаль "en_US"):
std::to_string(3.14); // "3.14" (точка как разделитель)
// В Германии (локаль "de_DE"):
std::to_string(3.14); // Может вернуть "3,14" (запятая)!
Естественно, что поддержка такой фичи чего-то да стоит.
Особенности модномолодежного подхода:
👉🏿 Функции std::from_chars, std::to_chars спроектированы быть настолько легкими и быстрыми, насколько это возможно на таком уровне абстракции.
👉🏿 Отсутствие намеренных динамических аллокаций. Только вы решаете, где расположена память по данные.
👉🏿 Отсутствие исключений. Функции возвращает объект ошибки, который явно нужно проверять руками.
👉🏿 Не проверяет локали.
👉🏿 Поддерживают частичный парсинг.
👉🏿 Поддержка явной гарантии round-trip. Если вы запишите в строку число с помощью std::to_chars и прочитаете его с помощью std::from_chars, то вы всегда получите изначальный результат. Главное, чтобы обе функции были вызваны с использованием одинаковой реализации стандартной библиотеки. Но у std::stoi, std::to_string и этого нет.
Если вы работаете в высоконагруженном или ограниченном по производительности окружении, то ваш выбор явно std::from_chars, std::to_chars. Обычно в коде таких приложений отказываются от использования исключений, поэтому проблем с код-стайлом не будет.
Возможность поэтапного парсинга также не оставляет выбора - используйте std::from_chars.
Если вы не паритесь за производительность, любите объекты, вам не нужен частичный парсинг или каждый раз при виде слова exception у вас не начинает идти пена изо рта, то придерживайтесь старого подхода.
Choose the right tool. Stay cool.
#cppcore #cpp11 #cpp17
Post #735
4.85K