Я немного знаю C, а теперь смотрю на C ++. Я привык к массивам символов для работы со строками C, но пока я смотрю код C ++, я вижу, что есть примеры, использующие как строковый тип, так и массивы char:
#include <iostream>
#include <string>
using namespace std;
int main () {
string mystr;
cout << "What's your name? ";
getline (cin, mystr);
cout << "Hello " << mystr << ".\n";
cout << "What is your favorite team? ";
getline (cin, mystr);
cout << "I like " << mystr << " too!\n";
return 0;
}
и
#include <iostream>
using namespace std;
int main () {
char name[256], title[256];
cout << "Enter your name: ";
cin.getline (name,256);
cout << "Enter your favourite movie: ";
cin.getline (title,256);
cout << name << "'s favourite movie is " << title;
return 0;
}
(оба примера с http://www.cplusplus.com )
Я полагаю, что это широко задаваемый (очевидный?) Вопрос, но было бы неплохо, если бы кто-нибудь мог сказать мне, в чем именно разница между этими двумя способами работы со строками в C ++ (производительность, интеграция API, способ каждого из них лучше, ...).
Спасибо.
Ответы:
Массив char - это просто массив символов:
Строка - это класс, который содержит массив символов, но автоматически управляет им за вас. Большинство реализаций строк имеют встроенный массив из 16 символов (поэтому короткие строки не фрагментируют кучу) и используют кучу для более длинных строк.
Вы можете получить доступ к строковому массиву символов следующим образом:
Строки C ++ могут содержать встроенные символы \ 0, знать их длину без подсчета, быстрее, чем массивы символов, выделенные кучей, для коротких текстов и защищают вас от переполнения буфера. Кроме того, они более читабельны и проще в использовании.
Однако строки C ++ не (очень) подходят для использования через границы DLL, потому что для этого потребуется, чтобы любой пользователь такой функции DLL был уверен, что он использует тот же самый компилятор и реализацию среды выполнения C ++, чтобы не рисковать, что его строковый класс будет вести себя по-другому.
Обычно строковый класс также освобождает свою память кучи в вызывающей куче, поэтому он сможет снова освободить память, только если вы используете общую (.dll или .so) версию среды выполнения.
Вкратце: используйте строки C ++ во всех ваших внутренних функциях и методах. Если вы когда-нибудь пишете .dll или .so, используйте строки C в ваших общедоступных (dll / so-visible) функциях.
источник
Аркаитц прав,
string
это управляемый тип. Для вас это означает , что вам не нужно беспокоиться о длине строки и не нужно беспокоиться об освобождении или перераспределении памяти строки.С другой стороны,
char[]
обозначения в приведенном выше случае ограничивают символьный буфер ровно 256 символами. Если вы попытались записать в этот буфер более 256 символов, в лучшем случае вы перезапишете другую память, которой «владеет» ваша программа. В худшем случае вы попытаетесь перезаписать память, которой вы не владеете, и ваша ОС сразу же убьет вашу программу.Нижняя граница? Строки намного удобнее для программистов, а символы char [] намного эффективнее для компьютера.
источник
Ну, строковый тип - это полностью управляемый класс для символьных строк, в то время как char [] по-прежнему тот, что был в C, байтовый массив, представляющий для вас символьную строку.
Что касается API и стандартной библиотеки, все реализовано в терминах строк, а не char [], но есть еще много функций из libc, которые получают char [], поэтому вам может потребоваться использовать его для них, кроме этого я бы всегда используйте std :: string.
С точки зрения эффективности, конечно, необработанный буфер неуправляемой памяти почти всегда будет быстрее для многих вещей, но примите во внимание сравнение строк, например, std :: string всегда имеет размер, чтобы сначала проверить его, а с char [] вы нужно сравнивать по характеру.
источник
Я лично не вижу причин, по которым можно было бы использовать char * или char [], кроме совместимости со старым кодом. std :: string не медленнее, чем использование c-строки, за исключением того, что он будет обрабатывать перераспределение за вас. Вы можете установить его размер при его создании и, таким образом, избежать перераспределения, если хотите. Его оператор индексации ([]) обеспечивает постоянный доступ по времени (и во всех смыслах этого слова то же самое, что и использование индексатора c-строк). Использование метода at также дает вам проверенные границы безопасности, чего вы не получите с c-строками, если вы его не напишете. Ваш компилятор чаще всего оптимизирует использование индексатора в режиме выпуска. С до-струнами легко возиться; такие вещи, как delete vs delete [], безопасность исключений, даже как перераспределить c-строку.
И когда вам нужно иметь дело с продвинутыми концепциями, такими как наличие строк COW и не-COW для MT и т. Д., Вам понадобится std :: string.
Если вы беспокоитесь о копиях, пока вы используете ссылки и ссылки на константы везде, где можете, у вас не будет никаких накладных расходов из-за копий, и это то же самое, что и с c-строкой.
источник
Строки имеют вспомогательные функции и автоматически управляют массивами символов. Вы можете объединить строки, для массива char вам нужно будет скопировать его в новый массив, строки могут изменить свою длину во время выполнения. Массивом char управлять сложнее, чем строкой, и некоторые функции могут принимать в качестве входных данных только строку, что требует преобразования массива в строку. Лучше использовать строки, они сделаны так, что не нужно использовать массивы. Если бы массивы были объективно лучше, у нас не было бы строк.
источник
Думайте о (char *) как о string.begin (). Существенная разница в том, что (char *) - это итератор, а std :: string - контейнер. Если вы придерживаетесь базовых строк, a (char *) даст вам то, что делает std :: string :: iterator. Вы можете использовать (char *), когда хотите использовать итератор, а также совместимость с C, но это исключение, а не правило. Как всегда, будьте осторожны с недействительностью итератора. Когда люди говорят (char *) небезопасно, они имеют в виду именно это. Это так же безопасно, как и любой другой итератор C ++.
источник
Одно из отличий - нулевое завершение (\ 0).
В C и C ++ char * или char [] будут принимать указатель на один char в качестве параметра и отслеживать по памяти до тех пор, пока не будет достигнуто значение памяти 0 (часто называемое нулевым терминатором).
Строки C ++ могут содержать встроенные символы \ 0, их длина известна без подсчета.
Вывод:
источник