Char * vs std::string в С++

Когда следует использовать std::string и когда я должен использовать char* для управления массивами char в С++?

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

Существуют ли другие сценарии?

Ответ 1

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

Я использую std::string/wstring для более или менее всего, что является фактическим текстом. char * полезен для других типов данных, хотя вы можете быть уверены, что он будет освобожден, как и должен. В противном случае std::vector - путь.

Вероятно, есть исключения из всего этого.

Ответ 2

Моя точка зрения:

  • Никогда не используйте char *, если вы не вызываете код "C".
  • Всегда используйте std::string: это проще, он более дружелюбен, оптимизирован, стандартный, это предотвратит появление ошибок, проверено и проверено на работоспособность.

Ответ 3

Использование исходной строки

Да, иногда вы действительно можете это сделать. При использовании массивов const char *, char, выделенных в стеке и строковых литералах, вы можете сделать это таким образом, что распределение памяти вообще отсутствует.

Написание такого кода требует часто большего мышления и заботы, чем использование строки или вектора, но с надлежащими методами это можно сделать. При использовании надлежащих методов код может быть безопасным, но вам всегда нужно убедиться, что при копировании в char [] у вас есть какие-то гарантии на длину скопированной строки, или вы грамотно проверяете и обрабатываете негабаритные строки. Не делать этого - это то, что дало strcpy семейству функций репутацию небезопасной.

Как шаблоны могут помочь писать безопасные буферы char

Что касается безопасности буферов 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;
}

Ответ 4

Вы должны использовать char* в следующих случаях:

  • Этот массив будет передан в параметре.
  • Вы заранее знаете максимальный размер вашего массива (вы его знаете или вы его навязываете).
  • Вы не будете преобразовывать этот массив.

На самом деле, в С++, char* часто используются для фиксированного небольшого слова, как опции, имя файла и т.д.

Ответ 5

Один раз, когда вы ДОЛЖНЫ использовать char *, а не std::string, вам понадобятся статические строковые константы. Причина этого в том, что вы не имеете никакого контроля над модулями заказа, инициализируя их статические переменные, а другой глобальный объект из другого модуля может ссылаться на вашу строку перед ее инициализацией. http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Static_and_Global_Variables

std::string профи:

  • управляет памятью для вас (строка может расти, а реализация будет выделять больший буфер)
  • Интерфейс программирования более высокого уровня, прекрасно работает с остальными STL.

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

Ответ 6

Когда использовать С++ std::string:

  • строки в целом более безопасны, чем char *. Обычно, когда вы делаете что-то с char *, вам нужно проверить все, чтобы убедиться, что все правильно, в строковом классе все это делается для вас.
  • Обычно при использовании char * вам нужно освободить выделенную память, вам не нужно делать это со строкой, так как она освободит свой внутренний буфер при уничтожении.
  • Строки хорошо работают с С++ stringstream, форматированный IO очень прост.

Когда использовать char *

  • Использование char * дает вам больше контроля над тем, что происходит "позади" сцен, что означает, что вы можете настроить производительность, если вам нужно.

Ответ 7

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

Ответ 8

Если вы хотите использовать библиотеки C, вам придется иметь дело с C-строками. То же самое относится, если вы хотите выставить свой API на C.

Ответ 9

Вы можете ожидать, что большинство операций с std::string (например, find) будут максимально оптимизированы, поэтому они, скорее всего, будут выполняться, по крайней мере, так же, как и чистая C-копия.

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

Вещи, на которые следует обратить внимание, - это, например, operator[] - большинство реализаций STL не выполняют проверку границ и должны перевести это на ту же операцию в базовом массиве символов. AFAIK STLPort может дополнительно выполнять проверку границ, после чего этот оператор будет немного медленнее.

Так что же вы используете std::string? Это освобождает вас от ручного управления памятью; изменение размера массива становится проще, и вам обычно приходится меньше думать о освобождении памяти.

Если вы беспокоитесь о производительности при изменении размера строки, там есть функция reserve, которую вы можете найти полезной.

Ответ 10

если вы используете массив символов в виде текста и т.д., используйте std::string более гибкий и простой в использовании. Если вы используете его для чего-то еще, например для хранения данных? использовать массивы (предпочитают векторы)

Ответ 11

Даже когда производительность важна, вам лучше использовать vector<char> - он позволяет заранее распределить память (метод reserve()) и поможет вам избежать утечек памяти. Использование vector:: operator [] приводит к накладным расходам, но вы всегда можете извлечь адрес буфера и точно его индексировать, если это был char *.

Ответ 12

AFAIK внутренне наиболее std::string реализует копию для записи, ссылается на семантику, чтобы избежать накладных расходов, даже если строки не передаются по ссылке.