Я вижу, что почти все современные API разработаны на языке C. Для этого есть причины: скорость обработки, язык низкого уровня, кроссплатформенность и так далее.

В настоящее время я программирую на C ++ из-за его объектной ориентации, использования строки, STL, но в основном потому, что это лучший язык C.

Однако, когда моим программам на C ++ необходимо взаимодействовать с C API, я действительно расстраиваюсь, когда мне нужно преобразовать типы char [] в строки C ++, затем обработать эти строки, используя его мощные методы, и, наконец, снова преобразовать из этих строк в char [] ( потому что API должен получить char []).

Если я повторю эти операции для миллионов записей, время обработки увеличится из-за задачи преобразования. По этой простой причине я считаю, что char [] в данный момент является препятствием для того, чтобы считать C ++ лучшим вариантом c.

Я хотел бы знать, чувствуете ли вы то же самое, если нет (я на это надеюсь!) Я действительно хотел бы знать, как лучше всего для C ++ сосуществовать с типами char [] без этих ужасных преобразований. Спасибо за внимание.

2
Edward 8 Авг 2009 в 03:45

6 ответов

Лучший ответ

У строкового класса C ++ много проблем, и да, то, что вы описываете, является одной из них.

В частности, невозможно выполнить обработку строки без создания копии строки, что может быть дорогостоящим.

А поскольку практически все алгоритмы обработки строк реализованы как члены класса, их можно только использовать в классе строк.

Решение, с которым вы, возможно, захотите поэкспериментировать, - это комбинация Boost.Range и Boost.StringAlgo.

Диапазон позволяет создавать последовательности из пары итераторов. Они не владеют данными, поэтому не копируют строку. они просто указывают на начало и конец строки char *.

А Boost.StringAlgo реализует все стандартные строковые операции как функции, не являющиеся членами, которые могут применяться к любой последовательности символов. Как, например, диапазон Boost.

Комбинация этих двух библиотек в значительной степени решает проблему. Они позволяют избежать копирования строк для их обработки.

Другое решение - хранить строковые данные как std::string все время . Когда вам нужно передать char* некоторой функции API, просто передайте ей адрес первого символа. (& str [0]).

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

4
jalf 7 Авг 2009 в 23:58

Если вы используете std::vector<char> вместо std::string, базовым хранилищем будет массив C, к которому можно получить доступ с помощью &someVec[0]. Однако вы теряете много std::string удобств, таких как operator+.

Тем не менее, я бы посоветовал просто избегать C API, которые максимально изменяют строки. Если вам нужно передать неизменяемую строку в функцию C, вы можете использовать c_str(), который работает быстро и не копирует в большинстве реализаций std::string.

3
bdonlan 7 Авг 2009 в 23:53

Я не совсем понимаю, что вы имеете в виду под «конверсией», но разве следующего недостаточно для перехода между char*, char[] и std::string?

char[] charString = {'a', 'b', 'c', '\0'};
std::string standardString(&charString[0]);
const char* stringPointer(standardString.c_str());
1
Steve Guidi 7 Авг 2009 в 23:52

Я не уверен, почему вы были бы ограничены использованием строк C и по-прежнему имеете среду, в которой выполняется код C ++, но если вам действительно не нужны накладные расходы на преобразование, не выполняйте преобразование. Просто напишите процедуры, которые работают со строками C.

Другая причина для преобразования в строки стиля C ++ - связанная безопасность.

0
Steve 8 Авг 2009 в 05:10

"... потому что это лучший C."

Ерунда. C ++ - намного худший диалект C. Проблемы, которые он решает, тривиальны, проблемы, которые он приносит, намного хуже, чем те, которые он решает.

-5
smcameron 7 Авг 2009 в 23:58

Я не думаю, что это так плохо, как вы думаете.

Преобразование char [] в std :: string требует затрат, но если вы собираетесь изменять строку, вам все равно придется заплатить эту стоимость, будь то преобразование в std :: string или копирование в другой char [] буфер.

Обратное преобразование (через string.c_str ()) обычно тривиально. Обычно он возвращает указатель на внутренний буфер (просто не передавайте этот буфер коду, который его изменит).

0
Ferruccio 7 Авг 2009 в 23:56