Почему Вы предпочитаете символ* вместо строки в C++?

Если мы ищем числа и простые слова, много корректных ответов были даны.

Однако, если мы ищем то, что мы обычно рассматриваем как палиндромы на письменном языке (например, "Собака, паника, в пагоде!"), корректный ответ должен был бы выполнить итерации запуска с обоих концов предложения, неалфавитно-цифровые символы пропуска индивидуально , и возвращение false, если какие-либо несоответствия найдены.

i = 0; j = length-1;

while( true ) {
  while( i < j && !is_alphanumeric( str[i] ) ) i++;
  while( i < j && !is_alphanumeric( str[j] ) ) j--;

  if( i >= j ) return true;

  if( tolower(string[i]) != tolower(string[j]) ) return false;
  i++; j--;
}

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

11
задан woot 16 June 2014 в 01:17
поделиться

12 ответов

Безопаснее использовать std :: string , потому что вам не нужно беспокоиться о выделении / освобождении памяти для строки. Класс C ++ 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 ");

Изменить:

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

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


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

27
ответ дан 3 December 2019 в 02:52
поделиться

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

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

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

5
ответ дан 3 December 2019 в 02:52
поделиться

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

1
ответ дан 3 December 2019 в 02:52
поделиться

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

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

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

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

2
ответ дан 3 December 2019 в 02:52
поделиться

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

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

1
ответ дан 3 December 2019 в 02:52
поделиться

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

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

0
ответ дан 3 December 2019 в 02:52
поделиться

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

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

0
ответ дан 3 December 2019 в 02:52
поделиться

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

0
ответ дан 3 December 2019 в 02:52
поделиться

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

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

-1
ответ дан 3 December 2019 в 02:52
поделиться

std::string is almost always preferred. Even for speed, it uses small array on the stack before dynamically allocating more for larger strings.

However, char* pointers are still needed in many situations for writing strings/data into a raw buffer (e.g. network I/O), which can't be done with std::string.

-2
ответ дан 3 December 2019 в 02:52
поделиться

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

strlen(infinitelengthstring)

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

string.length()
-1
ответ дан 3 December 2019 в 02:52
поделиться

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

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

-2
ответ дан 3 December 2019 в 02:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: