char * vs std :: string в c ++

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

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

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

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

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

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

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

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

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

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

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

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

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

 template  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  inline const BString & strcpy(BString &dst, const char *src) { return dst = src; } 

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

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

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

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

std::string pros:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • Являются ли массивы Java максимальным?
  • Присоединить элементы массива?
  • Есть ли у JavaScript метод, подобный «range ()» для создания диапазона в пределах предоставленных границ?
  • Я не хочу, чтобы моя надстройка Excel возвращала массив (вместо этого мне нужен UDF для изменения других ячеек)
  • Итерации по двум массивам одновременно в bash
  • Как получить String Array из файла arrays.xml
  • Класс Java Comparator для сортировки массивов
  • C # поиск ближайшего значения в массиве
  • Массив Java, поиск дубликатов
  • Как объявить массив в Python?
  • Получение массива Класс типа компонента
  • Interesting Posts

    Расширение не может содержать хранимое свойство, но почему статическое разрешено

    Android: получение общих настроек другого приложения

    Выберите все содержимое текстового поля, когда он получает фокус (Vanilla JS или jQuery)

    декомпилировать бинарное приложение, чтобы вернуться к исходному коду

    Marsmallow: изменение разрешений при запуске приложения

    Где хранятся переменные среды в реестре?

    Невозможно прокручивать хвост вверх или вниз по серверу

    AlarmManager не работает на нескольких устройствах

    Eclipse: JVM завершена. Код выхода = 2

    Как отправить Ctrl + Alt + F1 (и другие специальные нажатия клавиш) в окно X?

    Перебирайте все элементы управления в форме, даже в групповых ящиках

    Как вычесть X дней с даты с помощью Java-календаря?

    Чрезвычайно длинная assembly с Gradle (Android Studio)

    Применять несколько сводных функций по нескольким переменным по группам за один вызов

    Необоснованная производительность ноутбука

    Давайте будем гением компьютера.