|
Программирование >> Разработка устойчивых систем
Строки Обработка строк в символьных массивах отнимала массу времени у программистов С. При работе с символьным массивом программисту приходилось различать статические строки в кавычках и массивы, созданные в стеке и в куче, а также помнить, что в одних случаях передается char*, а в других приходится копировать целый массив. С учетом того, что операции со строками так широко распространены, символьные массивы превращались в источник сплошных недоразумений и ошибок. Однако несмотря на это, создание собственных строковых классов в течение долгих лет оставалось распространенным упражнением для начинающих программистов С++. Класс string стандартной библиотеки С++ раз и навсегда решает проблему работы с символьными массивами, он правильно выделяет память даже при конструировании копий и присваивании. Вам просто не придется думать об этих мелочах. В этой главе рассматривается класс string стандартного языка С++. Сначала мы разберемся, что же представляют собой строки С++ и чем они отличаются от традиционных символьных массивов С. Вы узнаете, какие операции выполняются с объектами string, и как класс string обеспечивает применение различных кодировок и преобразований строковых данных. Обработка текста относится к числу старейших задач программирования. Вполне понятно, что класс string в значительной степени основан на идеях и терминологии, традиционно использовавшейся в С и других языках. Это обстоятельство придаст вам уверенности во время изучения string. Какую бы идиому программирования вы ни выбрали, основные операции с классом string делятся на три категории: создание или модификация последовательности символов, хранящейся в string; проверка наличия или отсутствия элементов в string; преобразование между различными схемами представления символов в string. Часть материала этой главы была подготовлена Нэнси Николайсен (Nancy Nicolaisen). Что такое строка? в языке С строка представляет собой массив символов, последним элементом которого всегда является двоичный ноль (часто называемый нуль-терминатором). Между строками С++ и их прототипами С существуют заметные различия. Первое и самое важное из них состоит в том, что строковые объекты С++ скрывают физическое представление содержащихся в них символов. Вам не придется беспокоиться о размерах массива или о нуль-терминаторах. Объект string также содержит служебную информацию о размере и местонахождении буфера данных. Говоря точнее, строковый объект С++ знает свой начальный адрес в памяти, свое содержимое, свою длину в символах, а также максимальную длину в символах, до которой он может увеличиться без увеличения внутреннего буфера данных. Строки С++ существенно снижают вероятность самых распространенных и опасных ошибок программирования С: выхода за границы массива, попытки обращения к массиву через неинициализированный или ошибочный указатель, появление висячих указателей после освобождения блока памяти, в котором ранее хранился массив. Стандарт С++ не определяет конкретную структуру памяти для строкового класса. Предполагается, что эта архитектура является достаточно гибкой, чтобы по-разному реализовываться разработчиками компиляторов, но при этом гарантировать предсказуемое поведение для пользователей. В частности, в стандарте не определяются точные условия выделения памяти для хранения данных. Правила сформулированы таким образом, что они допускают реализацию на базе подсчета ссылок, но не делают ее обязательной. Впрочем, независимо от того, используется ли в реализации подсчет ссылок или нет, семантика должна сохраняться. Так, в языке С каждый символьный массив всегда занимает уникальный физический блок памяти. В С++ отдельные объекты string могут занимать или не занимать уникальные физические блоки памяти, но даже если хранение лишних копий данных предотвращается благодаря подсчету ссылок, с точки зрения программиста отдельные объекты должны работать так, словно каждый из них хранится в отдельном блоке. Пример: : СОЗ:StringStorage.h #ifndef STRINGSTORAGE H #define STRINGSTORAGE H #include <iostream> #include <string> #include ../TestSuite/Test.h :cout: using std using std using std :endl; :string: class StringStorageTest : public TestSuite::Test { public: void runO { string sl( 12345 ): Первая строка может быть скопирована во вторую или копирование может имитироваться подсчетом ссылок. Вы увидите, как каждая из этих операций выполняется средствами строковых объектов С++. string s2 = si; test (sl == s2); В любом случае эта команда должна изменять ТОЛЬКО si sl[0] = б; cout si = si endl; cout s2 = s2 endl; testjsl != s2); #endif STRINGSTORAGE H /:- ; C03:StringStorage.cpp {L} ../TestSuite/Test #include StringStorage.h int mainO { StringStorageTest t; t.runO; return t.reportO; } III:- Говорят, что в реализации, при которой уникальные копии создаются только при модификации строк, используется стратегия копирования при записи. Такое решение экономит время и память в тех случаях, когда строки только передаются по значению (а также в других ситуациях с доступом только для чтения). Пользователю класса string должно быть безразлично, основана реализация библиотеки на подсчете ссылок или нет. К сожалению, это правило выполняется далеко не всегда. В многопоточных программах практически невозможно безопасно использовать реализацию с подсчетом ссылок. Создание и инициализация строк С++ Создание и инициализация строк - вполне очевидные операции, обладающие достаточно гибкими возможностями. В приведенном ниже примере SmaUString.cpp первая строка imBlank объявляется, но не содержит исходного значения. В отличие от символьных массивов С, которые до момента инициализации содержат случайный и бессмысленный набор битов, imBlank содержит полезную информацию. Этот объект string инициализируется пустой строкой , он может правильно сообщить о своей нулевой длине и отсутствии элементов через функции класса. Следующая строка heyMom инициализируется литералом Where are my socks? . При такой форме инициализации конструктору string передается символьный массив, заключенный в кавычки. С другой стороны, standardReply инициализируется простым присваиванием. Последняя строка группы, useThisOneAgain, инициализируется существующим строковым объектом С++. Другими словами, этот пример демонстрирует следующие способы инициализации объектов string: создание пустого объекта string (инициализация объекта символьными данными откладывается на будущее); инициализация объекта string с передачей конструктору литерала - символьного массива, заключенного в кавычки; Многопоточное программирование будет рассматриваться в главе 10.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |