С++ 17 Назначение std::from_chars и std::to_chars?

До C++17 существовало множество методов для преобразования целых чисел, чисел с плавающей запятой и двойных чисел в строки и обратно. Например, для выполнения этих задач можно было использовать std::stringstream, std::to_string, std::atoi, std::stoi и другие. На что существует множество сообщений, в которых обсуждаются различия между этими методами.

Однако в C++ 17 появились std::from_chars и std::to_chars. На что я хотел бы знать причины введения другого средства преобразования в строки и из строк.

Во-первых, какие преимущества и функциональные возможности обеспечивают эти новые функции по сравнению с предыдущими методами?

Кроме того, есть ли какие-либо заметные недостатки у этого нового метода преобразования строк?

Я думаю, что они различаются тем, как они обрабатывают локали, распределение памяти и поведение исключений, но у меня нет под рукой подробностей.

alfC 27.04.2019 01:10

Из источника заметок «... В отличие от других функций синтаксического анализа в библиотеках C++ и C, std::from_chars не зависит от языкового стандарта, не выделяет и не выбрасывает....": en.cppreference.com/w/cpp/utility/from_chars

Richard Critten 27.04.2019 01:15

Одно слово: СКОРОСТЬ!!!!

NathanOliver 27.04.2019 01:18

Вот если бы только GCC и Clang закончили их реализацию!

Emile Cormier 18.03.2020 00:23
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
24
4
6 143
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Все эти ранее существовавшие методы должны были работать на основе так называемой локали. Локаль — это в основном набор параметров форматирования, которые определяют, например, какие символы считаются цифрами, какой символ использовать для десятичной точки, какой разделитель тысяч использовать и так далее. Однако очень часто вам это не нужно. Если вы просто, например, читаете файл JSON, вы знаете, что данные отформатированы определенным образом, нет причин искать, должна ли '.' быть десятичной точкой или нет каждый раз, когда вы ее видите. Новые функции, представленные в <charconv>, в основном жестко закодированы для чтения и записи чисел на основе форматирования, установленного для локали C по умолчанию. Нет возможности изменить форматирование, но поскольку форматирование не обязательно должно быть гибким, оно может быть очень быстрым…

Ответ принят как подходящий

std::stringstream — чемпион в тяжелом весе. Он принимает во внимание такие вещи, как пропитанная локаль потока, и его функциональность включает в себя такие вещи, как создание сторожевого объекта на время форматированной операции, чтобы иметь дело с проблемами, связанными с исключениями. Операции форматированного ввода и вывода в библиотеках C++ имеют репутацию быть тяжеловесным и медленным.

std::to_string менее интенсивен, чем std::istringstream, но все же возвращает std::string, конструкция которого, вероятно, включает динамическое распределение (менее вероятно с современными методами оптимизации коротких строк, но все же вероятно). И в большинстве случаев компилятору по-прежнему необходимо генерировать все многословие на месте вызова для поддержки объекта std::string, включая его деструктор.

std::to_chars спроектированы так, чтобы занимать как можно меньше места. Вы предоставляете буфер, и std::to_chars делает очень мало, кроме фактического форматирования числового значения в буфер, в определенном формате, без каких-либо соображений, специфичных для локали, с единственными накладными расходами на обеспечение достаточного размера буфера. Код, использующий std::to_chars, не требует динамического распределения.

std::to_chars также немного более гибок с точки зрения параметров форматирования, особенно со значениями с плавающей запятой. std::to_string не имеет параметров форматирования.

std::from_chars также является легковесным синтаксическим анализатором, которому не нужно выполнять какое-либо динамическое распределение и не нужно жертвовать электронами для решения проблем локали или накладных расходов на потоковые операции.

std::to_string также учитывает текущую локаль. Так что я бы сказал, что он не менее, а на самом деле более гибкий в плане форматирования…
Michael Kenzel 27.04.2019 01:28

to/from_chars разработаны как элементарные функции преобразования строк. У них есть два основных преимущества перед альтернативами.

  1. Они намного легче по весу. Они никогда не выделяют память (вы выделяете память для них). Они никогда не бросают исключений. Они также никогда не смотрят на локаль, что также повышает производительность.

    По сути, они разработаны таким образом, что на уровне API невозможно иметь более быстрые функции преобразования.

    Эти функции могут быть даже constexpr (это не так, хотя я не уверен, почему), в то время как более тяжелые версии с выделением и/или выбрасыванием не могут.

  2. У них есть явные гарантии возврата. Если вы преобразуете float/double в строку (без указанной точности), реализация будет требуется, чтобы сделать так, чтобы взятие этой точной последовательности символов и преобразование ее обратно в float/double давало значение бинарно-идентичный. Вы не получите эту гарантию от snprintf, stringstream или to_string/stof.

    Однако эта гарантия хороша только в том случае, если вызовы to_chars и from_chars используют одну и ту же реализацию. Таким образом, вы не можете ожидать отправки строки через Интернет на какой-либо другой компьютер, который может быть скомпилирован с другой реализацией стандартной библиотеки и получить то же самое float. Но это дает вам гарантии сериализации на компьютере.

Почему бы to/from_chars не иметь гарантий приема-передачи для разных реализаций? Если мы предположим, что ieee754, получим ли мы тогда гарантию приема-передачи между реализациями?

Justin 20.08.2019 02:51

@Justin: Даже если вы предполагаете IEEE (который является стандартным не), вам все равно придется точно указать, как будет работать округление. Что может помешать реализации более высокой производительности для конкретной части оборудования.

Nicol Bolas 20.08.2019 03:48

Это свойство преобразования round_trip — то, что нам было нужно в течение многих лет. Только наличие гарантий для работы с собственными результатами реализации немного угнетает, когда вы работаете с обменом XML или JSON между строками. Я профилировал from_chars, и это было примерно в 10 раз быстрее, чем при использовании Boost lexical_cast с классическим набором локали каждый раз (поскольку некоторые библиотеки изменяют его без восстановления и тем самым уничтожают любое независимое от локали хранилище).

gast128 10.02.2020 23:56

@ gast128: Дело в том, что вы всегда можете извлечь конкретную реализацию в свое приложение (или использовать общедоступную), которая даст вам все преимущества производительности при сохранении того же API.

Nicol Bolas 11.02.2020 05:44

Другие вопросы по теме