Когда я должен использовать std::string
и когда я должен использовать char*
для управления массивами char
s в C ++?
Похоже, вам следует использовать, char*
если производительность (скорость) имеет решающее значение, и вы готовы принять некоторые из рискованных дел из-за управления памятью.
Можно ли рассмотреть другие сценарии?
char *
почти нет накладных расходов.std::string
Я не знаю, какие именно накладные расходы , скорее всего, это зависит от реализации. Я вряд ли ожидаю, что накладные расходы будут намного больше, чем у простого указателя char. Поскольку у меня нет копии стандарта, я не могу подробно описать какие-либо гарантии, предоставляемые стандартом. Любая разница в производительности, вероятно, будет зависеть от выполняемых операций.std::string::size
может хранить размер рядом с символьными данными и, таким образом, быть быстрее, чемstrlen
.append(const string&)
иappend(const char*, size_t)
вместоoperator+=()
.Моя точка зрения такова:
источник
Использование необработанной строки
Да, иногда это действительно удается. При использовании массивов const char *, char, выделенных в стеке, и строковых литералов вы можете сделать это таким образом, чтобы память не выделялась вообще.
Написание такого кода часто требует большего мышления и осторожности, чем использование строки или вектора, но с помощью надлежащих методов это можно сделать. При правильной технике код может быть безопасным, но вам всегда нужно быть уверенным, что при копировании в char [] у вас либо есть гарантии относительно длины копируемой строки, либо вы проверяете и обрабатываете слишком большие строки изящно. Невыполнение этого требования и дало семейству функций strcpy репутацию небезопасных.
Как шаблоны могут помочь в написании безопасных буферов символов
Что касается безопасности буферов char [], могут помочь шаблоны, поскольку они могут создавать инкапсуляцию для обработки размера буфера за вас. Подобные шаблоны реализованы, например, Microsoft, чтобы обеспечить безопасную замену strcpy. Пример здесь извлечен из моего собственного кода, в реальном коде гораздо больше методов, но этого должно быть достаточно, чтобы передать основную идею:
template <int Size> class BString { char _data[Size]; public: BString() { _data[0]=0; // note: last character will always stay zero // if not, overflow occurred // all constructors should contain last element initialization // so that it can be verified during destruction _data[Size-1]=0; } const BString &operator = (const char *src) { strncpy(_data,src,Size-1); return *this; } operator const char *() const {return _data;} }; //! overloads that make conversion of C code easier template <int Size> inline const BString<Size> & strcpy(BString<Size> &dst, const char *src) { return dst = src; }
источник
char*
строки не всегда в стеке.char *str = (char*)malloc(1024); str[1024] = 0;
Один случай , который вы должны использовать ,
char*
а неstd::string
когда вам нужны статические строковые константы. Причина в том, что у вас нет никакого контроля над модулями заказа, инициализирующими свои статические переменные, а другой глобальный объект из другого модуля может ссылаться на вашу строку до ее инициализации. http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Static_and_Global_Variablesstd::string
плюсы:std::string
Минусы: - два разных экземпляра строки STL не могут использовать один и тот же базовый буфер. Поэтому, если вы переходите по значению, вы всегда получаете новую копию. - есть некоторое снижение производительности, но я бы сказал, что если ваши требования не являются специальными, это незначительно.источник
Вам следует подумать об использовании
char*
в следующих случаях:На самом деле, в C ++
char*
часто используются фиксированные маленькие слова, такие как параметры, имя файла и т. Д.источник
Когда использовать c ++ std :: string:
Когда использовать char *
источник
Используйте (const) char * в качестве параметров, если вы пишете библиотеку. Реализации std :: string различаются между разными компиляторами.
источник
Если вы хотите использовать библиотеки C, вам придется иметь дело с C-строками. То же самое применимо, если вы хотите предоставить свой API для C.
источник
Вы можете ожидать, что большинство операций с std :: string (например, например
find
) будут максимально оптимизированы, поэтому они, вероятно, будут работать как минимум так же хорошо, как и чистый аналог C.Также стоит отметить, что итераторы std :: string довольно часто сопоставляются с указателями в базовом массиве char. Таким образом, любой алгоритм, который вы разрабатываете поверх итераторов, по сути идентичен тому же алгоритму поверх char * с точки зрения производительности.
На что следует обратить внимание, например,
operator[]
большинство реализаций STL не выполняют проверку границ и должны преобразовывать это в ту же операцию с базовым массивом символов. AFAIK STLPort может дополнительно выполнять проверку границ, после чего этот оператор будет немного медленнее.Так что же дает вам использование std :: string? Это освобождает вас от ручного управления памятью; изменить размер массива становится проще, и обычно вам нужно меньше думать об освобождении памяти.
Если вы беспокоитесь о производительности при изменении размера строки, есть
reserve
функция, которая может вам пригодиться.источник
если вы используете массив символов в подобном тексте и т.д., используйте std :: string более гибким и простым в использовании. Если вы используете его для чего-то еще, например, для хранения данных? использовать массивы (предпочитать векторы)
источник
Даже когда производительность имеет решающее значение, лучше использовать
vector<char>
- он позволяет заранее выделить память (метод резерв ()) и поможет избежать утечек памяти. Использование vector :: operator [] приводит к накладным расходам, но вы всегда можете извлечь адрес буфера и проиндексировать его точно так же, как если бы это был char *.источник
AFAIK внутренне большинство std :: string реализует копирование при записи, семантику подсчета ссылок, чтобы избежать накладных расходов, даже если строки не передаются по ссылке.
источник