Зачем использовать std::string над строками c-style в С++?
"Всегда нужно использовать std::string по строкам c-style (char *
)" - это совет, который подходит почти каждый исходный код размещен здесь. Хотя совет, без сомнения, хорош, актуальные вопросы, которые рассматриваются, не позволяют подробно рассмотреть аспект вопроса почему?. Этот вопрос должен служить в качестве заполнителя для того же самого.
Хороший ответ должен охватывать следующие аспекты (подробно):
- Зачем использовать
std::string
над строками c-style в С++?
- Каковы недостатки (если таковые имеются) практики, упомянутой в
#1
?
- Каковы сценарии, где противоположность рекомендаций, упомянутых в
#1
, является хорошей практикой?
Ответы
Ответ 1
- std::string управляет собственной памятью, поэтому вы можете легко копировать, создавать и уничтожать их.
- Вы не можете использовать свой собственный буфер как std::string.
- Вам нужно передать строку c/buffer к тому, что ожидает взять на себя ответственность за буфер, например, от библиотеки сторонних C.
Ответ 2
Ну, если вам просто нужен массив символов, std::string дает мало преимуществ. Но с этим сталкиваешься, как часто это происходит? Обертывая массив char с дополнительными функциями, такими как std::string, вы получаете как мощность, так и эффективность для некоторых операций.
Например, для определения длины массива символов требуется "подсчет" символов в массиве. Напротив, std::string обеспечивает эффективную работу для этой конкретной задачи. (см. fooobar.com/questions/85652/...)
- Для мощности, эффективности и здравомыслия
- Увеличенный объем памяти, чем "просто" массив char
- Когда вам просто нужен массив символов
Ответ 3
3) Совет всегда использует string
, конечно же, должен быть принят с обрывом здравого смысла. Строковые литералы const char[]
, и если вы передадите литерал функции, которая принимает const char*
(например, std::ifstream::open()
), нет никакой точки, обертывающей ее в std::string
.
Ответ 4
A char * - это в основном указатель на символ. То, что C часто делает, указывает на то, что этот указатель указывает на первый символ в массиве.
An std::string - это класс, который очень похож на вектор. Внутри он обрабатывает хранилище массива символов и предоставляет пользователю несколько функций-членов для управления указанным массивом, а также несколькими перегруженными операторами.
Причины использования char * по std::string:
C backwards-compatibility.
Performance (potentially).
char*s have lower-level access.
Причины использования std::string над char *:
Much more intuitive to use.
Better searching, replacement, and manipulation functions.
Reduced risk of segmentation faults.
Пример:
char * должен использоваться в сочетании с массивом char или с динамически распределенным массивом char. В конце концов, указатель бесполезен, если он фактически не указывает на что-то. Это в основном используется в программах на C:
char somebuffer[100] = "a string";
char* ptr = somebuffer; // ptr now points to somebuffer
cout << ptr; // prints "a string"
somebuffer[0] = 'b'; // change somebuffer
cout << ptr; // prints "b string"
обратите внимание, что при изменении "somebuffer" также изменяется "ptr". Это потому, что в этом случае somebuffer является фактической строкой. ptr просто указывает/ссылается на него.
С std::string это менее странно:
std::string a = "a string";
std::string b = a;
cout << b; // prints "a string"
a[0] = 'b'; // change 'a'
cout << b; // prints "a string" (not "b string")
Здесь вы можете видеть, что изменение "a" не влияет на "b", потому что "b" - это настоящая строка.
Но на самом деле главное отличие заключается в том, что с массивами char вы отвечаете за управление памятью, тогда как std::string делает это за вас. В С++ существует очень мало причин использовать массивы char по строкам. 99 раз из 100 вам лучше со строкой.
Пока вы полностью не поймете управление памятью и указатели, просто сохраните себе некоторые головные боли и используйте std::string.
Ответ 5
Зачем использовать std::string над строками c-style в С++?
Основная причина заключается в том, что он освобождает вас от управления временем жизни строковых данных. Вы можете просто рассматривать строки как значения и позволить компилятору/библиотеке беспокоиться об управлении памятью.
Ручное управление распределением памяти и временем жизни является утомительным и подверженным ошибкам.
Каковы недостатки (если таковые имеются) практики, упомянутой в № 1?
Вы отдаете мелкомасштабный контроль над распределением памяти и копированием. Это означает, что вы получаете стратегию управления памятью, выбранную вашим поставщиком инструментальных средств, а не выбранную в соответствии с потребностями вашей программы.
Если вы не будете осторожны, вы можете получить много ненужных копий данных (в нерекомментированной реализации) или манипуляции счетным счетом (в обновленной версии)
В проекте на смешанном языке любая функция, аргументы которой используются std::string или любая структура данных, содержащая std::string, не будет использоваться напрямую с других языков.
Каковы сценарии, где противоположность рекомендаций, упомянутых в № 1, является хорошей практикой?
У разных людей будут разные мнения по этому поводу, но IMO
- Для аргументов функции передача строк в "const char *" является хорошим выбором, поскольку она позволяет избежать unessacery copy/refcouning и дает гибкость вызывающего абонента в том, что они передают.
- Для вещей, используемых при взаимодействии с другими языками, у вас мало выбора, кроме как использовать строки c-style.
- Если у вас есть ограничение на длину, возможно, быстрее использовать массивы фиксированного размера.
- При работе с очень длинными строками может быть лучше использовать конструкцию, которая будет определенно скопирована, а не скопирована (например, массив символов, завернутый в shared_ptr), или вообще использовать совсем другой тип структуры данных.
Ответ 6
В общем, вы всегда должны использовать std::string, так как он менее подвержен ошибкам. Помните, что накладные расходы памяти std::string значительны. Недавно я провел несколько экспериментов над служебными данными std::string. В общем, это около 48 байт! Статья находится здесь: http://jovislab.com/blog/?p=76.