char * vs std:: string в c++ [закрыто]


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

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

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

12 75

12 ответов:

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

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

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

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

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

использование необработанной строки

Да, иногда вы действительно можете сделать это. При использовании 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* в следующих случаях:

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

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

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

std::string плюсы:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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