Зачем использовать строки c в C++?
Вопрос
Есть ли в настоящее время веская причина использовать C-строки в C++?В моем учебнике они используются в некоторых моментах в примерах, и мне кажется, что было бы проще просто использовать std::string.
Решение
Единственная причина, по которой мне приходилось их использовать, - это взаимодействие со сторонними библиотеками, использующими строки стиля C.Могут также возникнуть экзотические ситуации, когда вы будете использовать строки в стиле C из соображений производительности, но чаще всего использование методов для строк C++, вероятно, происходит быстрее из-за встраивания, специализации и т. д.
Вы можете использовать c_str()
во многих случаях при работе с такого рода API, но вы должны знать, что возвращаемый символ char * является константным, и вам не следует изменять строку с помощью этого указателя.В таких ситуациях вы все равно можете использовать вектор<char> и, по крайней мере, получить преимущество от более простого управления памятью.
Другие советы
Еще пара замечаний по управлению памятью:
Строки C являются типами POD, поэтому их можно разместить в сегменте данных вашего приложения, доступном только для чтения.Если вы объявите и определите std::string
константы в области пространства имен, компилятор сгенерирует дополнительный код, который запускается перед main()
это вызывает std::string
конструктор для каждой константы.Если в вашем приложении много константных строк (например,если вы создали код C++, использующий константные строки), строки C могут быть предпочтительнее в этой ситуации.
Некоторые реализации std::string
поддерживать функцию единого входа («оптимизация короткой строки» или «оптимизация небольшой строки»), где std::string
класс содержит хранилище для строк до определенной длины.Это увеличивает размер std::string
но часто значительно снижает частоту выделения/освобождения свободной памяти, повышая производительность.Если ваша реализация std::string
не поддерживает единый вход, затем создается пустой std::string
в стеке все равно будет выполняться распределение свободного хранилища.В этом случае использование временных строк C, выделенных в стеке, может оказаться полезным для критически важного к производительности кода, использующего строки.Конечно, при этом нужно быть осторожным, чтобы не выстрелить себе в ногу.
Потому что именно так они поступают из многочисленных API/библиотек?
Допустим, в вашем коде есть строковые константы, что является довольно распространенной необходимостью.Лучше определить их как строки C, чем как объекты C++ — более легкие, переносимые и т. д.Теперь, если вы собираетесь передавать эти строки различным функциям, было бы неплохо, если бы эти функции принимали строку C вместо того, чтобы требовать строковый объект C++.
Конечно, если строки изменяемы, гораздо удобнее использовать строковые объекты C++.
Контроль памяти.Недавно мне пришлось обрабатывать строки (фактически объекты из базы данных) размером около 200-300 МБ в многопоточном приложении.Это была ситуация, когда еще одна копия строки могла разорвать 32-битное адресное пространство.Мне нужно было точно знать, сколько существует копий строки.Хотя я пропагандист STL, я тогда использовал char *, потому что это давало мне гарантию того, что не будет выделено никакой дополнительной памяти или даже дополнительной копии.Я точно знал, сколько места для этого потребуется.
Кроме того, в стандартной обработке строк STL отсутствуют некоторые замечательные функции C для обработки/анализа строк.К счастью, std::string имеет метод c_str() для константного доступа к внутреннему буферу.Однако, чтобы использовать printf(), вам все равно придется использовать char * (какая сумасшедшая идея команды C++ не включать функциональность, подобную (s)printf, одну из самых полезных функций, когда-либо существовавших в C.Я надеюсь, что boost::format скоро будет включен в STL.
Если функция требует постоянный string Я по-прежнему предпочитаю использовать const char* (или const wchar_t*), даже если программа использует std::string, CString, EString или что-то еще.
В большой базе кода слишком много источников строк, чтобы быть уверенным, что вызывающая сторона получит строку в виде std::string, а 'const char*' является наименьшим общим знаменателем.
В учебниках используются строки C старой школы, поскольку многие базовые функции по-прежнему ожидают их в качестве аргументов или возвращают их.Кроме того, это дает некоторое представление о базовой структуре строки в памяти.
Если код C++ «глубокий» (близок к ядру, сильно зависит от библиотек C и т. д.), вы можете явно захотеть использовать строки C, чтобы избежать большого количества преобразований в std::string и из него.Конечно, если вы взаимодействуете с другими языковыми доменами (Python, Ruby и т. д.), вы можете сделать это по той же причине.В противном случае используйте std::string.
В некоторых сообщениях упоминаются проблемы с памятью.Это может быть хорошей причиной избегать std::string, но char*, вероятно, не лучшая замена.Это все еще объектно-ориентированный язык.Ваш собственный строковый класс, вероятно, лучше, чем char*.Это может быть даже более эффективно — например, вы можете применить оптимизацию малых строк.
В моем случае я пытался получить строки объемом около 1 ГБ из файла размером 2 ГБ, поместить их в записи примерно с 60 полями, а затем отсортировать их 7 раз по разным полям.Код моего предшественника с char* занимал 25 часов, мой код выполнялся за 1 час.
Потратив слишком много времени на отладку правил инициализации и всех мыслимых реализаций строк на нескольких платформах, мы требуем, чтобы статические строки были const char*.
Потратив слишком много времени на отладку плохого кода char* и утечек памяти, я предлагаю, чтобы все нестатические строки были строковыми объектами некоторого типа...пока профилирование не покажет, что можно и нужно сделать что-то лучше ;-)
При наличии выбора обычно нет причин выбирать примитивные строки C (char*
) над строками C++ (std::string
).Однако зачастую у вас нет такой роскоши, как выбор.Например, std::fstream
Конструкторы принимают строки C по историческим причинам.Кроме того, библиотеки C (как вы уже догадались!) используют строки C.
В вашем собственном коде C++ лучше всего использовать std::string
и извлеките строку C объекта по мере необходимости, используя c_str()
функция std::string
.
Это зависит от библиотек, которые вы используете.Например, при работе с МФЦ, часто проще использовать CString при работе с различными частями Windows API.Также кажется, что он работает лучше, чем std::string в приложениях Win32.
Однако std::string является частью стандарта C++, поэтому, если вам нужна лучшая переносимость, используйте std::string.
Для таких приложений, как большинство встраиваемых платформ, где нет роскоши кучи для хранения обрабатываемых строк и где требуется детерминированное предварительное выделение строковых буферов.
Строки c не несут накладных расходов, связанных с классом.
Строки c обычно могут привести к более быстрому написанию кода, поскольку они ближе к машинному уровню.
Это не значит, что с их помощью нельзя писать плохой код.Их можно использовать неправильно, как и любую другую конструкцию.
Существует множество библиотечных запросов, которые требуют их по историческим причинам.
Научитесь использовать строки c и stl и используйте каждую из них, когда это имеет смысл.
1) «строковая константа» — это строка C (const char *), преобразование ее в const std::string& — это процесс времени выполнения, не обязательно простой или оптимизированный.2) библиотека fstream использует строки в стиле c для передачи имен файлов.
Мое практическое правило — передавать const std::string&, если я все равно собираюсь использовать данные как std::string (скажем, когда я сохраняю их в векторе), и const char * в других случаях.
Устаревший код, который не знает std::string.Кроме того, до C++11 открытие файлов с помощью std::ifstream или std::ofstream было возможно только с помощью const char* в качестве входных данных имени файла.
Строки STL, безусловно, гораздо проще использовать, и я не вижу причин не использовать их.
Если вам нужно взаимодействовать с библиотекой, которая принимает в качестве аргументов только строки в стиле C, вы всегда можете вызвать метод c_str() класса строк.
Обычно это делается потому, что вам нравится писать о переполнении буфера при обработке строк.Считаемые строки настолько превосходят завершаемые строки, что трудно понять, почему разработчики C вообще использовали завершаемые строки.Тогда это было плохое решение;сейчас это плохое решение.