C ++ - символ * против строки * - PullRequest
14 голосов
/ 28 января 2011

Если у меня есть указатель, который указывает на строковую переменную array of chars, есть ли разница между набором:

char *name = "name";

И,

string name = "name";

Ответы [ 7 ]

29 голосов
/ 28 января 2011

Да, есть разница.Главным образом потому, что вы можете изменить свою строку, но вы не можете изменить свою первую версию - но компилятор C ++ даже не предупредит вас, что это запрещено, если вы попытаетесь.

Поэтому всегда используйте вторуюверсия.

Если вам необходимо использовать указатель на символ по любой причине, сделайте его const:

char const* str = "name";

Теперь, если вы попытаетесь изменить содержимоеиз str, компилятор запретит это (правильно).Вы также должны поднять уровень предупреждения вашего компилятора на ступеньку выше: тогда он предупредит, что ваш первый код (например, char* str = "name") допустим, но не рекомендуется.

9 голосов
/ 28 января 2011

Для начала, вы, вероятно, хотите изменить

string *name = "name";

читать

string name = "name";

Первая версия не будет компилироваться, потому что string* и char* - это принципиально разные типы.

Разница между string и char* заключается в том, что char* является просто указателем на последовательность. Этот подход к манипулированию строками основан на языке программирования C и является родным способом кодирования строк в C ++. С строками C работать немного сложнее - нужно быть уверенным, что для них правильно выделено пространство, чтобы избежать выхода из конца буфера, который они занимают, чтобы поместить их в изменяемую память, чтобы избежать ошибок сегментации и т. Д. Основные функции для манипулирования ими в <cstring>. Большинство программистов на C ++ не советуют использовать строки в стиле C, поскольку с ними сложнее работать, но они все еще поддерживаются как для обратной совместимости, так и в качестве «наименьшего общего знаменателя», из которого могут строиться низкоуровневые API.

Стиль C ++ string - это объект, инкапсулирующий строку. Детали управления памятью не видны пользователю (хотя вы можете быть уверены, что вся память является непрерывной). Он использует перегрузку операторов, чтобы упростить использование некоторых общих операций, таких как конкатенация, а также поддерживает несколько функций-членов, предназначенных для выполнения высокоуровневых операций, таких как поиск, замена, подстроки и т. Д. Они также предназначены для взаимодействия с алгоритмами STL, хотя C строки в стиле также могут делать это.

Короче говоря, как программист C ++ вам, вероятно, лучше использовать тип string. Это безопаснее и немного проще в использовании. Все еще полезно знать о строках в стиле C, потому что вы наверняка столкнетесь с ними в своей карьере программиста, но, вероятно, лучше не использовать их в своих программах, где string также может использоваться, если нет веских причин для этого.

8 голосов
/ 28 января 2011

Да, второй недействителен C ++!(Он не скомпилируется).

Вы можете создать string разными способами, но один из способов таков:

string name = "name";

Обратите внимание, что * 1007 не требуется*, поскольку нам не нужно объявлять его как указатель.

4 голосов
/ 28 января 2011

char* name = "name" должен быть недействительным, но компилируется в большинстве систем для обратной совместимости со старыми днями, когда не было const, и что он сломал бы большие объемы унаследованного кода, если бы он не компилировался.Хотя обычно появляется предупреждение.

Опасность заключается в том, что вы получаете указатель на доступные для записи данные (доступные для записи в соответствии с правилами C ++), но если вы действительно пытаетесь записать их, вы вызываете Undefined Behavior и языкправила должны пытаться защитить вас от этого настолько, насколько это возможно.

Правильная конструкция -

const char * name = "name";

С вышесказанным все в порядке, даже в C ++.Использование строки не всегда более корректно.

Ваше второе утверждение должно быть действительно

std::string name = "name";

string - это класс (на самом деле typedef из basic_string<char,char_traits<char>,allocator<char>), определенный в стандартной библиотеке, следовательно, в пространстве именstd (как basic_string, char_traits и allocator)

Существуют различные сценарии, в которых использование строки намного предпочтительнее использования массивов char.Например, в вашем непосредственном случае вы МОЖЕТЕ изменить его.Так что

name[0] = 'N';

(преобразовать первую букву в верхний регистр) допустимо для строки, а не для char * (неопределенное поведение) или const char * (не компилируется).Вам будет разрешено изменить строку, если у вас будет char name[] = "name";

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

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

Кроме того, basic_string фактически не выполняет многие строковые операции, которые выполняются вместо этого через char_traits.(Это позволяет использовать специальные C-функции, которые хорошо оптимизированы).

std :: string, следовательно, является лучшим способом управления строками, когда вы обрабатываете динамические строки, созданные и передаваемые во время выполнения.(а не просто литералы).

Вы редко будете использовать строку * (указатель на строку).Если вы сделаете это, это будет указатель на объект, как и любой другой указатель.Вы не сможете распределить его так, как вы.

1 голос
/ 22 апреля 2012

C ++ строковый класс инкапсулирует char C-подобную строку.Это гораздо удобнее (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
0 голосов
/ 28 января 2011
string *name = "name";

Не компилируется в GCC.

0 голосов
/ 28 января 2011

Да, 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
...