Если у меня есть указатель, указывающий на строковую переменную array of chars
, существует ли разница между вводом:
char *name = "name";
и
string name = "name";
Если у меня есть указатель, указывающий на строковую переменную array of chars
, существует ли разница между вводом:
char *name = "name";
и
string name = "name";
Да, это разница. В основном потому, что вы можете изменить свою строку, но вы не можете изменить свою первую версию, но компилятор С++ даже не предупредит вас, что это запрещено, если вы попытаетесь.
Поэтому всегда используйте вторую версию.
Если вам нужно использовать указатель char по любой причине, сделайте его const
:
char const* str = "name";
Теперь, если вы попытаетесь изменить содержимое str
, компилятор запретит это (правильно). Вы также должны повысить уровень предупреждения вашего компилятора до отметки: тогда он предупредит, что ваш первый код (т.е. char* str = "name"
) является законным, но не рекомендуется.
Да, второй недействителен С++! (Он не будет компилироваться).
Вы можете создать string
разными способами, но один из способов:
string name = "name";
Обратите внимание, что нет необходимости в *
, так как нам не нужно объявлять его как указатель.
Для начала вы, вероятно, захотите изменить
string *name = "name";
читать
string name = "name";
Первая версия не будет компилироваться, потому что string*
и a char*
являются принципиально разными типами.
Разница между string
и a char*
заключается в том, что char*
является просто указателем на последовательность. Этот подход манипулирования строками основан на языке программирования C и является родным способом, в котором строки закодированы в С++. Строки C немного сложны в работе - вы должны быть уверены, что правильно распределите пространство для них, чтобы не покидать буфер, который они занимают, чтобы поместить их в изменяемую память, чтобы избежать сбоев сегментации и т.д. Основные функции для управления ими находятся в <cstring>
. Большинство программистов на С++ советуют не использовать строки C-стиля, поскольку по своей сути они сложнее работать, но они по-прежнему поддерживаются как для обратной совместимости, так и как "самый низкий общий знаменатель", с которым могут скомпенсироваться низкоуровневые API.
A С++ - стиль string
- это объект, инкапсулирующий строку. Детали управления памятью не видны пользователю (хотя вы можете гарантировать, что вся память смежна). Он использует перегрузку оператора, чтобы упростить использование некоторых общих операций, таких как конкатенация, а также поддерживает несколько функций-членов, предназначенных для выполнения высокоуровневых операций, таких как поиск, замена, подстроки и т.д. Они также предназначены для взаимодействия с алгоритмами STL, хотя C стильные строки также могут сделать это.
Короче говоря, как программист на С++, вам, вероятно, лучше использовать тип string
. Это безопаснее и немного проще в использовании. По-прежнему полезно знать о строках в стиле C, потому что вы обязательно столкнетесь с ними в своей карьере программирования, но, вероятно, лучше не использовать их в своих программах, где string
также можно использовать, если нет веских оснований для этого.
char* name = "name"
должен быть недействительным, но компилируется в большинстве систем для обратной совместимости с старыми днями, когда не было const, и что он сломал бы большой объем старого кода, если он не скомпилировался. Обычно он получает предупреждение.
Опасность состоит в том, что вы получаете указатель на записываемые данные (записываемые в соответствии с правилами С++), но если вы действительно попытались написать на него, вы будете ссылаться на Undefined Behavior, и языковые правила должны пытаться защитить вас от этого насколько это возможно.
Правильная конструкция
const char * name = "name";
Нет ничего плохого в вышеупомянутом, даже в С++. Использование строки не всегда корректно.
Ваше второе утверждение должно быть действительно
std::string name = "name";
string - это класс (на самом деле typedef of basic_string<char,char_traits<char>,allocator<char>
), определенный в стандартной библиотеке, поэтому в пространстве имен std (as are basic_string, char_traits и allocator)
Существуют различные сценарии, в которых использование строки намного предпочтительнее использования массивов char. Например, в вашем ближайшем случае вы можете изменить его. Так
name[0] = 'N';
(преобразование первой буквы в верхний регистр) имеет значение со строкой, а не с поведением char * (undefined) или const char * (не будет компилироваться). Вам будет разрешено изменять строку, если у вас есть char name[] = "name";
Однако, если вы хотите добавить символ в строку, конструкция std::string является единственной, которая позволит вам сделать это чисто. Со старым C API вам нужно будет использовать strcat(), но это будет недействительным, если вы не выделили достаточно памяти для этого.
std::string управляет памятью для вас, поэтому вам не нужно вызывать malloc() и т.д. Фактически распределитель, третий параметр шаблона, управляет памятью внизу - basic_string делает запросы о том, сколько памяти ему нужно, но отделяется от используемая фактическая технология выделения памяти, поэтому вы можете использовать пулы памяти и т.д. для эффективности даже с std::string.
Кроме того, basic_string фактически не выполняет многие из строковых операций, которые выполняются вместо char_traits. (Это позволяет использовать специализированные C-функции, которые хорошо оптимизированы).
std::string, следовательно, лучший способ управлять вашими строками, когда вы обрабатываете динамические строки, созданные и переданные во время выполнения (а не только литералы).
Вы редко используете строку * (указатель на строку). Если вы это сделаете, это будет указатель на объект, как и любой другой указатель. Вы не сможете выделить его так, как вы это делали.
Строковый класс С++ инкапсулирует строку char C-like. Это гораздо удобнее (http://www.cplusplus.com/reference/string/string/).
для наследия вы всегда можете "извлечь" char указатель из строковой переменной, чтобы иметь дело с ним как указатель char:
char * cstr;
string str ("Please split this phrase into tokens");
cstr = new char [str.size()+1];
strcpy (cstr, str.c_str()); //here str.c_str() generate null terminated char* pointer
//str.data() is equivalent, but without null on end
Да, char*
- это указатель на массив символов, который является строкой. string *
- это указатель на массив std::string
(который очень редко используется).
string *name = "name";
"name" - это const char*
, и он никогда не был бы преобразован в std::string*
. Это приведет к ошибке компиляции.
Действительное объявление:
string name = "name";
или
const char* name = "name"; // char* name = "name" is valid, but deprecated
string *name = "name";
Не компилируется в GCC.