C ++ 17 Назначение std :: from_chars и std :: to_chars? - PullRequest
5 голосов
/ 27 апреля 2019

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

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

С одной стороны, какие преимущества и функциональные возможности предоставляют эти новые функции по сравнению с предыдущими методами?

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

Ответы [ 3 ]

9 голосов
/ 27 апреля 2019

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, аналогично, облегченный синтаксический анализатор, который не требует динамического распределения и не должен жертвовать электронами для решения локальных проблем, илинакладные расходы на потоковые операции.

6 голосов
/ 27 апреля 2019

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

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

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

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

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

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

1 голос
/ 27 апреля 2019

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

...