Вы можете передать std :: string по ссылке, если они велики, чтобы избежать копирования или указателя на экземпляр, поэтому я не вижу никакого реального преимущества с помощью указателей на символы.
Я использую std :: string / wstring для более или менее всего, что является фактическим текстом. char *
полезен для других типов данных, хотя вы можете быть уверены, что он будет освобожден, как и должен. В противном случае std :: vector - путь.
Вероятно, есть исключения для всего этого.
Моя точка зрения:
Один раз, когда вы ДОЛЖНЫ использовать char*
, а не std::string
, вам понадобятся статические строковые константы. Причина этого в том, что у вас нет никакого контроля над модулями заказа, инициализируйте их статические переменные, а другой глобальный объект из другого модуля может ссылаться на вашу строку перед ее инициализацией. http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Static_and_Global_Variables
std::string
профи:
std::string
минус: - два разных экземпляра строки STL не могут использовать один и тот же базовый буфер. Поэтому, если вы проходите по значению, вы всегда получаете новую копию. - есть некоторые штрафы за производительность, но я бы сказал, если ваши требования не являются особенными, это незначительно.
Вы должны рассмотреть возможность использования char*
в следующих случаях:
На самом деле, в C ++, char*
часто используются для фиксированного маленького слова, в качестве параметров, имени файла и т. д. ...
Если вы хотите использовать библиотеки C, вам придется иметь дело с C-строками. То же самое относится, если вы хотите выставить свой API на C.
Когда использовать строки c ++ std :: string:
Когда использовать char *
Использовать (const) char * в качестве параметров, если вы пишете библиотеку. Строковые реализации различаются между разными компиляторами.
AFAIK внутренне большинство std :: string реализует копию при записи, ссылается на семантику, чтобы избежать накладных расходов, даже если строки не переданы по ссылке.
, если вы используете массив символов в виде текста и т. д., используйте std :: string более гибким и простым в использовании. Если вы используете его для чего-то еще, например для хранения данных? использовать массивы (предпочитают векторы)
Даже когда производительность имеет решающее значение, вам лучше использовать vector<char>
- она позволяет заранее распределить память (метод reserve ()) и поможет вам избежать утечек памяти. Использование vector :: operator [] приводит к накладным расходам, но вы всегда можете извлечь адрес буфера и точно его индексировать, если это был char *.
Да, иногда вы действительно можете это сделать. При использовании const char *, массивов символов, выделенных в стеке и строковых литералах, вы можете сделать это таким образом, что распределение памяти вообще отсутствует.
Написание такого кода требует часто большего мышления и заботы, чем использование строки или вектор, но с надлежащими методами это можно сделать. При правильных методах код может быть безопасным, но вам всегда нужно убедиться, что при копировании на 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;
}
Вы можете ожидать, что большинство операций над строкой std :: (например, find
) будут максимально оптимизированы, поэтому они, скорее всего, будут выполняться, по крайней мере, так же, как и чистая C-копия.
Также стоит отметить, что итераторы std :: string довольно часто отображают указатели в базовый массив. Таким образом, любой алгоритм, который вы разрабатываете поверх итераторов, по существу идентичен тому же алгоритму в верхней части char * с точки зрения производительности.
Вещи, которые следует учитывать, например, operator[]
- большинство реализаций STL не выполняют проверку границ и должны перевести это на ту же операцию в базовый массив символов. AFAIK STLPort может дополнительно выполнить проверку границ, и в этот момент этот оператор будет немного медленнее.
Итак, что делает использование std :: string для вас? Это освобождает вас от ручного управления памятью; изменение размера массива становится проще, и вам обычно приходится меньше думать о освобождении памяти.
Если вы беспокоитесь о производительности при изменении размера строки, есть функция reserve
, которую вы можете найти полезной.