Подтвердить что ты не робот

Когда следует использовать 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* является лучшим выбором? Кроме того, при запуске нового проекта лучше всего быть совместимым с использованием или просто взять тот, который лучше всего подходит для текущего фрагмента кода?

4b9b3361

Ответ 1

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

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

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

  • Гарантируется, что оно будет действительным. A const char* должен быть проверен на то, что он является нулевым, и вполне возможно передать неверные данные - данные не имеют нулевого терминатора. Такое появление в значительной степени гарантировано приведет к краху или к худшему.

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

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

Ответ 2

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

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

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

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

Помимо этих дополнительных точек я просто подписался на все три точки из ответа Ангела.

Ответ 3

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

В этом случае ваша подпись функции будет выглядеть следующим образом

void foo (std::string & str);

и вот так, если аргумент const

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

Здесь есть преимущества этого ключевого слова const, которое вы можете посмотреть здесь

Ответ 4

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

Ответ 5

Вместо использования

void foo(std::string str); 

вы можете использовать

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

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

void foo(const char* str);

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

Ответ 6

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

Ответ 7

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

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

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

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

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