Почему вы предпочитаете char * вместо строки, в С++?

Я программист C, пытающийся написать код на С++. Я слышал, что string в С++ был лучше, чем char* с точки зрения безопасности, производительности и т.д., Однако иногда кажется, что char* - лучший выбор. Кто-то предположил, что программисты не должны использовать char* в С++, потому что мы могли бы делать все, что char* могло бы сделать со строкой, и было бы более безопасным и быстрым.

Вы когда-нибудь использовали char* в С++? Каковы конкретные условия?

Ответ 1

Безопаснее использовать std::string, потому что вам не нужно беспокоиться о распределении/освобождении памяти для строки. Класс С++ std::string скорее всего будет использовать массив char*. Однако класс будет управлять распределением, перераспределением и освобождением внутреннего массива для вас. Это устраняет все обычные риски, связанные с использованием необработанных указателей, таких как утечки памяти, переполнение буфера и т.д.

Кроме того, это также невероятно удобно. Вы можете копировать строки, добавлять к строке и т.д., Без необходимости вручную предоставлять буферное пространство или использовать такие функции, как strcpy/strcat. С std::string он так же прост, как с помощью операторов = или +.

В принципе, это:

 std::string s1 = "Hello ";
 std::string s2 = s1 + "World";

по сравнению с...

 const char* s1 = "Hello";
 char s2[1024]; // How much should I really even allocate here?
 strcpy(s2, s1);
 strcat(s2, " World ");

Edit:

В ответ на ваше изменение относительно использования char* в С++: многие программисты на С++ утверждают, что никогда не следует использовать char*, если вы не работаете с некоторой функцией API/устаревшей, которая требует этого, и в этом случае вы можете используйте функцию std::string::c_str() для преобразования std::string в const char*.

Однако я бы сказал, что в С++ есть законное использование C-массивов. Например, если производительность абсолютно важна, небольшой C-массив в стеке может быть лучшим решением, чем std::string. Вы также можете написать программу, в которой вам необходим абсолютный контроль над распределением/освобождением памяти, и в этом случае вы использовали бы char*. Кроме того, как было указано в разделе комментариев, std::string не гарантирует, что вы будете иметь непрерывный буфер записи *, поэтому вы не можете напрямую писать из файла в std::string, если вам нужна ваша программа для быть полностью переносимым. Однако, если вам нужно это сделать, std::vector, вероятно, будет предпочтительнее использовать необработанный C-массив.


* Хотя в С++ 11 это изменилось, так что std::string предоставляет вам смежный буфер

Ответ 2

Хорошо, вопрос сильно изменился с тех пор, как я впервые ответил.

Нативные массивы char - это кошмар управления памятью и переполнения буфера по сравнению с std::string. Я всегда предпочитаю использовать std::string.

Тем не менее, массив char может быть лучшим выбором в некоторых случаях из-за ограничений производительности (хотя std::string может быть быстрее в некоторых случаях - сначала измерьте!) или запрет использования динамической памяти во встроенной среде, и т.д.

Ответ 3

В общем, std::string - это более чистый и безопасный способ, потому что он устраняет бремя управления памятью от программиста. Основная причина, по которой она может быть быстрее, чем char *, заключается в том, что std::string хранит длину строки. Таким образом, вам не нужно выполнять работу по итерации по всему массиву символов, ища завершающий символ NULL каждый раз, когда вы хотите сделать копию, добавить и т.д.

При этом вы все равно найдете множество программ на С++, которые используют сочетание std::string и char *, или даже написали свои собственные строковые классы с нуля. В старых компиляторах std::string был памятью и не обязательно так быстро, как это могло бы быть. Это со временем стало лучше, но некоторые высокопроизводительные приложения (например, игры и серверы) все еще могут извлечь выгоду из ручных манипуляций с строкой и управления памятью.

Я бы рекомендовал начать с std::string или, возможно, создать для него обертку с более полезными функциями (например, start_with(), split(), format() и т.д.). Если вы обнаружите, что при сопоставлении кода, который строковая манипуляция является узким местом или использует слишком много памяти, вы можете решить, хотите ли вы принять дополнительные риски и тестирование, которые требует пользовательская библиотека строк.

СОВЕТ. Один из способов обойти проблемы с памятью и использовать std::string - использовать встроенную базу данных, такую ​​как SQLite, Это особенно полезно при создании и обработке чрезвычайно больших списков строк, а производительность лучше, чем вы могли ожидать.

Ответ 4

C char * строки не могут содержать символы '\ 0'. Строка С++ может обрабатывать нулевые символы без проблем. Если пользователи вводят строки, содержащие \0, и вы используете строки C, ваш код может выйти из строя. Существуют также проблемы безопасности, связанные с этим.

Ответ 5

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

Что-то еще, но тот факт, что std::string скрывает все это от вас, делает его гораздо более удобным.

Ответ 6

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

Изменить: чтобы понять, почему строка может быть более эффективной, прочитайте книги Херба Саттера - он обсуждает способ внутренней реализации строки для использования Lazy Initialization в сочетании с ссылкой.

Ответ 7

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

Если вам нужно полагаться на конкретный макет char в памяти для других оптимизаций, попробуйте std::vector<char>. Если у вас есть непустой вектор vec, вы можете получить указатель char*, используя &vec[0] (вектор должен быть непустым).

Ответ 8

Короткий ответ, я этого не делаю. Исключение составляет то, когда я использую библиотеки сторонних разработчиков, которые их требуют. В таких случаях я пытаюсь придерживаться std::string:: c_str().

Ответ 9

Сравните и сравните следующие примеры C и С++:

strlen(infinitelengthstring)

против

string.length()

Ответ 10

Во всей моей профессиональной карьере у меня была возможность использовать std::string только в двух проектах. У всех остальных были свои собственные классы строк:)

Сказав, что для нового кода я обычно использую std::string, когда могу, за исключением границ модулей (функции, экспортируемые библиотеками dll/shared), где я склонен выявлять интерфейс C и избегать типов С++ и проблем с двоичным несовместимости между компиляторами и реализациями std-библиотек.

Ответ 11

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

Однако во многих ситуациях во многих ситуациях все еще нужны указатели char * для записи строк/данных в необработанный буфер (например, сетевой ввод-вывод), что невозможно сделать с помощью std::string.

Ответ 12

Единственный раз, когда я недавно использовал строку char C-style в программе на С++, был в проекте, который должен был использовать две библиотеки C, которые (конечно) использовали строки C исключительно. Преобразование назад и вперед между двумя типами строк сделало код действительно запутанным.

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