Вопрос

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

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

Есть ли другие сценарии, которые стоит рассмотреть?

Это было полезно?

Решение

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

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

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

Другие советы

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

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

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

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

std::string плюсы:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top