Когда следует использовать std :: string над символьными массивами?

Я сижу и думаю о том, должен ли я использовать const char* или же const std::string& довольно часто, когда я разрабатываю интерфейсы классов и когда дело доходит до этого, я часто чувствую, что в одной руке 6, а в другой — полдюжины.

Возьмите следующие два прототипа функции:

void foo(const char* str);
void foo(std::string str);

Если foo Функция заключалась в том, чтобы хранить строку, я бы сказал, что второй вариант лучше из-за возможности передавать строку и использовать семантику перемещения, где это возможно. Однако если foo нужно только прочитать строку, const char* решение будет лучше?

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

Итак, мои вопросы таковы:

Существуют ли четко определенные личные или иные соглашения, std::string или же const char* лучший выбор? Кроме того, при запуске нового проекта лучше всего согласовываться с использованием или просто брать тот, который лучше всего соответствует текущему фрагменту кода?

32

Решение

const char* это возврат к C. Я бы сказал, что в приличном C ++, единственное использование для этого в extern "C" API-интерфейсы.

std::string имеет ряд преимуществ:

  1. Обеспечивает постоянное время size() функция. Обнаружение длины const char* занимает линейное время.

  2. Это гарантированно будет действительным. const char* должен быть проверен на нулевое значение, и вполне возможно передать неверные данные — данные, в которых отсутствует нулевой терминатор. Такое происшествие в значительной степени гарантированно приведет к сбою или еще хуже.

  3. Он совместим со стандартными алгоритмами.

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

51

Другие решения

Просто несколько заметок из личного опыта. Если вы работаете над проектом c ++ (согласно добавленному вами тегу), придерживайтесь std::string при условии, сколько вы можете. Не пытайтесь заново изобрести самую основную из всех структур, всемогущую строку. Я видел несколько проектов, в которых они заново изобрели основную строку, а затем потратили месяцы на ее настройку.

В случае вашего проекта C ++ с момента, когда вы ввели char* Переменная вы возвращаетесь к стандартным функциям C, таким как strlen() а также strcpy (просто чтобы назвать два …). И с этого момента ваш проект начинает превращаться в беспорядок, с ручным распределением памяти и т. Д …

Если вам нужно взаимодействовать со сторонними библиотеками, которые принимают const char* в качестве их параметра (и я полагаю, вы доверяете этим библиотекам — то есть: вы доверяете, они не const_cast убери постоянство, чтобы творить плохие вещи с твоей бедной верёвкой) ты можешь использовать std::string::c_str() чтобы получить const char* из вашей строки.

В случае, если вам нужно взаимодействовать с библиотеками, которые имеют методы, принимающие char* Я настоятельно рекомендую вам взять копию вашей строки c_str() и использовать это как входящий параметр в библиотеку (конечно, не забудьте удалить лишнюю копию).

Помимо этих дополнительных баллов, я просто подписываюсь на все три балла из ответа Анжью.

19

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

В этом случае ваша подпись функции станет такой

void foo (std :: string &ул);

и так, если аргумент постоянный

void foo (const std :: string &ул);

Есть преимущества этого константного ключевого слова, которое вы можете посмотреть Вот

6

Вместо того, чтобы использовать

void foo(std::string str);

вы могли бы использовать

void foo(const std::string& str);

который был бы эквивалентно

void foo(const char* str);

с точки зрения использования, потому что при передаче ссылки не выделяется память. Но для строк в C ++ я бы определенно использовал std::string, Для случайных данных или C-совместимых интерфейсов я бы не стал.

4

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

4

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

3

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

Это потому, что вы всегда должны использовать string если вы не можете использовать его. Так что ситуации, когда вы должны использовать массив символов вместо string:

  1. Использование API, который поддерживает C так что вы не можете использовать string,
  2. Передача данных между exe а также dll, Не рекомендуется обмениваться типами данных, которые имеют конструктор и / или деструктор, между exe а также dll

Если вы беспокоитесь о производительности, после компиляции со всеми включенными оптимизациями string становится похожим на массив символов, может, в некоторых случаях, дает еще лучшую производительность, например, если вам нужно получить количество символов, которое он содержит.

Что касается производительности, вы всегда можете перейти по ссылке, как уже упоминалось в других ответах, если вам нужно передать указатель на массив символов, вы можете использовать метод c_str() который возвращается const указатель на первый символ, если вам нужно передать указатель (не const указатель) вы можете (но на самом деле не должны) передать его так: &str[0],

1
По вопросам рекламы [email protected]