Проектирование строкового класса в C ++ - PullRequest
5 голосов
/ 30 августа 2010

Мне нужно спроектировать (и в какой-то момент написать код) «настраиваемый» класс строк в C ++.Мне было интересно, не могли бы вы сообщить мне о любых проблемах с документацией и дизайном, в первую очередь, и о потенциальных подводных камнях, о которых мне следует знать.Ссылки приветствуются, как и определение проблем (если таковые имеются) с текущими строковыми библиотеками (Qstring, std :: string и другими).

Спасибо.

Ответы [ 7 ]

14 голосов
/ 30 августа 2010

Несмотря на критику, я думаю, что это правильный вопрос.

std::string не является панацеей. Похоже, кто-то взял класс из чистого OO и выгрузил его в C ++, что, вероятно, и так.

Совет 1: Предпочитайте методы, не являющиеся членами, не являющимися друзьями

Теперь, когда это сказано, в этот час интернационализации, я бы определенно посоветовал вам разработать класс, который бы поддерживал Unicode. И я говорю Unicode, а не UTF-8 или UTF-16. Я думаю, что неуместно разрабатывать класс, который будет содержать данные в заданной кодировке. Вы можете предоставить методы для вывода информации в различных форматах.

Совет 2: Поддержка Unicode

Тогда на схемах выделения памяти есть ряд точек:

  • Оптимизация небольших строк: класс содержит предварительно выделенное пространство для нескольких символов (дюжины или двух) и, таким образом, избегает выделения кучи для этих
  • Копировать при записи: различные строки совместно используют буфер, поэтому копирование обходится дешево, когда одна строка должна изменить свое содержимое, она копирует буфер, если она не является единственным владельцем -> проблема в том, что многопоточность приводит к дополнительным затратам здесь и было показано, что для техники общего назначения эти накладные расходы могут превзойти фактическую стоимость копирования
  • Неизменяемость: «новые» языки, такие как Java, C# или Python, используют неизменяемые строки. Думайте об этом как о пуле строк, все строки, содержащие «Fooo», будут указывать на один и тот же буфер. Обратите внимание, что эти языки поддерживают сборку мусора, что очень помогает.

Я бы лично выбрал здесь «Оптимизацию небольших строк» ​​(хотя она не исключительна для двух других) просто потому, что она проста в реализации и должна приносить вам пользу (стоимость выделения кучи, проблемы с ссылками).

Две другие техники несколько сложны в условиях многопоточности, и они, вероятно, подвержены ошибкам и вряд ли принесут реальную выгоду, если не будут тщательно обработаны.

И вот мой последний совет:

Совет 3: Не реализовывайте внутреннюю блокировку при попытке поддержки многопоточности

Это замедлит класс при использовании в контексте SingleThreaded и не принесет столько пользы, сколько вы думаете при использовании в многопоточном.

Наконец, вы можете найти что-то, отвечающее вашим вкусам (или получить несколько указателей), просматривая существующий код. Я не обещаю показывать "гладкие" интерфейсы, хотя:

  • ICU UnicodeString : поддержка Unicode, по крайней мере
  • std :: string : более 100 методов-членов (с учетом различных перегрузок)
  • llvm StringRef : обратите внимание, сколько алгоритмов реализовано как методы-члены: '(
3 голосов
/ 30 августа 2010

Effective STL Скотта Мейерса содержит интересную дискуссию о возможных методах реализации std::string, хотя она охватывает довольно сложные вопросы, такие как копирование при записи и подсчет ссылок.

2 голосов
/ 30 августа 2010

Херб Саттер дает образец пользовательского класса строк в GotW # 29 . Вы можете использовать его для начала.

2 голосов
/ 30 августа 2010

В зависимости от того, что такое «настройка» (например, пользовательский распределитель), вы можете сделать это с помощью параметра шаблона класса std :: basic_string.

1 голос
/ 30 августа 2010

С точки зрения общего назначения «новый» строковый класс идеально сочетает в себе хорошие моменты std :: string, CString, QString и других. Несколько очков в случайном порядке:

  • MFC CString поддерживает его использование в printf-подобных функциях из-за очень специфической реализации. Если вам нужна или нужна эта функция, я рекомендую купить книгу Джорджа Шеперда "MFC Internals". Хотя книга написана в 1996 году (!), Описание того, как реализована CString, должно стоить того. http://www.amazon.com/MFC-Internals-Microsoft-Foundation-Architecture/dp/0201407213/ref=sr_1_1?ie=UTF8&s=books&qid=1283176951&sr=8-1
  • Убедитесь, что ваш класс string хорошо работает со всеми интерфейсами, с которыми вы будете его использовать (iostreams, Windows API, printf * и т. Д.)
  • Не стремитесь к полной поддержке юникода (как в: сортировка, кластеры графем, ...), поскольку это будет означать, что ваш класс никогда не будет выполнен, но подумайте о том, чтобы сделать его классом wchar_t с опциями преобразования.
  • Подумайте о том, чтобы функция ctor /, которая создает ваши строковые объекты из char *, всегда принимала определенную кодировку массивов символов. (Может быть полезным в смешанных средах UTF-8 / других наборов символов.)
  • Посмотрите на полный интерфейс CString и на полный интерфейс std: string и решите, что вам нужно, и что вы можете пропустить.
  • Посмотрите на QString, чтобы увидеть, что пропускают два других.
  • Do not не обеспечивает неявное преобразование ни в char / wchar_t *
  • Рассмотрите возможность добавления удобных функций преобразования в / из числовых типов.
  • Не пишите строковый класс без полного набора подробных модульных тестов!
0 голосов
/ 30 августа 2010

Проблема с std :: string заключается в том, что вы не можете изменить это.Иногда вам нужны основы std :: string, но вы не согласны с реализацией вашей библиотеки c ++.

В качестве примера, использование поточно-ориентированного подсчета ссылок означает много блокировок (или, по крайней мере, заблокированных операций).Кроме того, если большинство ваших строк короткие (потому что вы знаете, что это так), вам может потребоваться класс строк, оптимизированный для этого варианта использования.

Так что даже если вам нравится std ::Строковый API, или, по крайней мере, научился жить с ним, есть место для «конкурирующих реализаций», которые более или менее похожи на рабочие.и подавляющее большинство из них поместились бы, скажем, в 25-байтовый фиксированный буфер, который уменьшил бы много нового / удаляющего давление.

0 голосов
/ 30 августа 2010

Мир не нуждается в другом классе строк. Это домашнее задание? Если нет, используйте std::string.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...