Зачем использовать строки c в C ++? - PullRequest
18 голосов
/ 21 сентября 2008

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

Ответы [ 18 ]

22 голосов
/ 21 сентября 2008

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

Вы можете использовать метод c_str() во многих случаях при работе с API такого рода, но вы должны знать, что возвращаемый тип char * является const, и вам не следует изменять строку через него указатель. В подобных ситуациях вы все равно можете использовать вектор и, по крайней мере, получить преимущество от более простого управления памятью.

14 голосов
/ 21 сентября 2008

Еще пара замечаний по управлению памятью:

Строки C являются типами POD, поэтому они могут быть размещены в сегменте данных только для чтения вашего приложения. Если вы объявите и определите std::string константы в области имен, компилятор сгенерирует дополнительный код, который выполняется до main(), который вызывает конструктор std::string для каждой константы. Если в вашем приложении много константных строк (например, если вы сгенерировали код C ++, который использует константные строки), в этой ситуации предпочтительнее использовать строки C.

Некоторые реализации std::string поддерживают функцию под названием SSO («оптимизация коротких строк» ​​или «оптимизация небольших строк»), где класс std::string содержит хранилище для строк до определенной длины. Это увеличивает размер std::string, но часто значительно уменьшает частоту распределения / освобождения свободного хранилища, улучшая производительность. Если ваша реализация std::string не поддерживает единый вход, то создание пустого std::string в стеке все равно будет выполнять выделение свободного хранилища. Если это так, то использование временных строк C, выделенных в стеке, может быть полезно для критичного к производительности кода, который использует строки. Конечно, вы должны быть осторожны, чтобы не выстрелить себе в ногу, когда вы делаете это.

8 голосов
/ 21 сентября 2008

Потому что так они поступают из многочисленных API / библиотек?

3 голосов
/ 21 сентября 2008

Контроль памяти. Недавно мне пришлось обрабатывать строки (на самом деле большие двоичные объекты из базы данных) размером около 200-300 МБ в многопоточном приложении. Это была ситуация, когда одна-единственная копия строки могла взорвать 32-битное адресное пространство. Я должен был точно знать, сколько существует копий этой строки. Хотя я евангелист STL, я использовал char * тогда, потому что это давало мне гарантию, что не было выделено никакой дополнительной памяти или даже дополнительной копии. Я точно знал, сколько места ему понадобится.

Кроме того, стандартная обработка строк в STL упускает некоторые замечательные функции C для обработки / анализа строк. К счастью, std :: string имеет метод c_str () для постоянного доступа к внутреннему буферу. Чтобы использовать printf (), вы все равно должны использовать char *, хотя (что за сумасшедшая идея команды C ++ не включать (s) printf-подобные функции, одна из самых полезных функций КОГДА-ЛИБО в C. скоро будет включен в STL.

3 голосов
/ 21 сентября 2008

Допустим, в вашем коде есть строковые константы, что является довольно распространенной потребностью. Лучше определить их как строки C, чем как объекты C ++ - более легкие, переносимые и т. Д. Теперь, если вы собираетесь передавать эти строки различным функциям, было бы хорошо, если бы эти функции принимали строку C вместо того, чтобы требовать C ++ строковый объект.

Конечно, если строки изменчивы, тогда гораздо удобнее использовать строковые объекты C ++.

2 голосов
/ 22 сентября 2008

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

В моем случае я пытался извлечь строки размером около 1 ГБ из файла объемом 2 ГБ, заполнить их записями, содержащими около 60 полей, а затем отсортировать их 7 раз по разным полям. Мой код предшественника занял 25 часов с символом *, мой код работал за 1 час.

2 голосов
/ 24 сентября 2008

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

Потратив слишком много времени на отладку плохого char * кода и утечек памяти, я предлагаю, чтобы все нестатические строки были чем-то вроде строкового объекта ... пока профилирование не покажет, что вы можете и должны делать что-то лучше; )

2 голосов
/ 21 сентября 2008

Учебники содержат строки старой школы C, поскольку многие базовые функции все еще ожидают их в качестве аргументов или возвращают их. Кроме того, он дает некоторое представление о базовой структуре строки в памяти.

2 голосов
/ 21 сентября 2008

Если функции требуется строка константа , я все равно предпочитаю использовать 'const char *' (или const wchar_t *), даже если программа использует std :: string, CString, EString или что-то еще.

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

2 голосов
/ 21 сентября 2008

Если код C ++ «глубокий» (близок к ядру, сильно зависит от библиотек C и т. Д.), Вы можете явно использовать строки C, чтобы избежать большого количества преобразований в и из std :: string. Если вы взаимодействуете с другими языковыми доменами (Python, Ruby и т. Д.), Вы можете сделать это по той же причине. В противном случае используйте std :: string.

...