Я сижу и думаю о том, должен ли я использовать 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*
лучший выбор? Кроме того, при запуске нового проекта лучше всего согласовываться с использованием или просто брать тот, который лучше всего соответствует текущему фрагменту кода?
const char*
это возврат к C. Я бы сказал, что в приличном C ++, единственное использование для этого в extern "C"
API-интерфейсы.
std::string
имеет ряд преимуществ:
Обеспечивает постоянное время size()
функция. Обнаружение длины const char*
занимает линейное время.
Это гарантированно будет действительным. const char*
должен быть проверен на нулевое значение, и вполне возможно передать неверные данные — данные, в которых отсутствует нулевой терминатор. Такое происшествие в значительной степени гарантированно приведет к сбою или еще хуже.
Он совместим со стандартными алгоритмами.
Если вы беспокоитесь о влиянии производительности на необходимость создания std::string
чтобы вызвать функцию, рассмотрите возможность использования подхода, используемого стандартной библиотекой — измените функцию, чтобы вместо нее использовать пару итераторов. Затем вы можете обеспечить удобную перегрузку, принимая const std::string&
делегирование к паре итераторов.
Просто несколько заметок из личного опыта. Если вы работаете над проектом c ++ (согласно добавленному вами тегу), придерживайтесь std::string
при условии, сколько вы можете. Не пытайтесь заново изобрести самую основную из всех структур, всемогущую строку. Я видел несколько проектов, в которых они заново изобрели основную строку, а затем потратили месяцы на ее настройку.
В случае вашего проекта C ++ с момента, когда вы ввели char*
Переменная вы возвращаетесь к стандартным функциям C, таким как strlen()
а также strcpy
(просто чтобы назвать два …). И с этого момента ваш проект начинает превращаться в беспорядок, с ручным распределением памяти и т. Д …
Если вам нужно взаимодействовать со сторонними библиотеками, которые принимают const char*
в качестве их параметра (и я полагаю, вы доверяете этим библиотекам — то есть: вы доверяете, они не const_cast
убери постоянство, чтобы творить плохие вещи с твоей бедной верёвкой) ты можешь использовать std::string::c_str()
чтобы получить const char*
из вашей строки.
В случае, если вам нужно взаимодействовать с библиотеками, которые имеют методы, принимающие char*
Я настоятельно рекомендую вам взять копию вашей строки c_str()
и использовать это как входящий параметр в библиотеку (конечно, не забудьте удалить лишнюю копию).
Помимо этих дополнительных баллов, я просто подписываюсь на все три балла из ответа Анжью.
std::string
всегда должен быть первым выбором в C ++. Чтобы избежать дополнительных затрат на копирование, вы почти всегда должны передавать аргумент как ссылку и const
ссылка везде и всегда, когда это возможно.
В этом случае ваша подпись функции станет такой
void foo (std :: string &ул);
и так, если аргумент постоянный
void foo (const std :: string &ул);
Есть преимущества этого константного ключевого слова, которое вы можете посмотреть Вот
Вместо того, чтобы использовать
void foo(std::string str);
вы могли бы использовать
void foo(const std::string& str);
который был бы эквивалентно
void foo(const char* str);
с точки зрения использования, потому что при передаче ссылки не выделяется память. Но для строк в C ++ я бы определенно использовал std::string
, Для случайных данных или C-совместимых интерфейсов я бы не стал.
std :: string лучше, чем использование raw char *, когда вам нужно управлять распределением, освобождением и проблемой размера, чтобы быть осторожным при любом переполнении, потере, что вы не пересекаете границу размера. Принимая во внимание, что std :: string это все заботятся через абстракцию
Если вы хотите лучше обрабатывать ваши данные (в вашем случае это будет строка), я бы сказал, что идти с char *. Это даст вам лучший доступ к вашей строке и использованию памяти.
Но если вам не нужно беспокоиться о производительности и управлении памятью, вы можете легко использовать std :: string.
Ну, я бы немного перефразировал ваш вопрос. Вы должны спросить, когда следует использовать массив символов вместо std::string
,
Это потому, что вы всегда должны использовать string
если вы не можете использовать его. Так что ситуации, когда вы должны использовать массив символов вместо string
:
C
так что вы не можете использовать string
,exe
а также dll
, Не рекомендуется обмениваться типами данных, которые имеют конструктор и / или деструктор, между exe
а также dll
Если вы беспокоитесь о производительности, после компиляции со всеми включенными оптимизациями string
становится похожим на массив символов, может, в некоторых случаях, дает еще лучшую производительность, например, если вам нужно получить количество символов, которое он содержит.
Что касается производительности, вы всегда можете перейти по ссылке, как уже упоминалось в других ответах, если вам нужно передать указатель на массив символов, вы можете использовать метод c_str()
который возвращается const
указатель на первый символ, если вам нужно передать указатель (не const
указатель) вы можете (но на самом деле не должны) передать его так: &str[0]
,