Почему вы предпочитаете 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 в отсутствие вышеупомянутого ограничения.