Программирование >>  Обобщенные обратные вызовы 

1 ... 3 4 5 [ 6 ] 7 8 9 ... 84


неплохо, но надо не забывать об ends: ostrstream temp( buf, buflen ); temp setw(4) i ends;

/. Простота использования и ясность, strstream немного уступает stri ngstream в плане простоты использования и ясности кода. Они оба требуют создания временного объекта. При использовании strstream вы до.тжны не забывать добавлять ends для завершения строки, и эту его особенность можно определить как нечто между безвкусно и опасно . Если вы забудете сделать это, возникнет опасность чтения после конца буфера (если вы полагаетесь только на завершающий нулевой символ). Даже раскритикованная нами функция spri ntf не поступает так, и всегда завершает строку нулевым символом. Но зато использование strstream таким образом, как это показано в примере 3-3, не требует вызова функции . strC) для получения конечного результата. (Конечно, если вы поступите иначе и позволите strstream со.здать собственный буфер, вам потребуется не только вызов . str() для получения конечного результата, но и вызов -freeze(false), поскольку иначе strstreambuf не будет освобождать выделенную память.)

2. Эффективность (возможность непосредственного использования существующих буферов). При создании объекта ostrstream с передачей ему указателя на существующий буфер нам не требуется выполнять никакого дополнительного распределения памяти; ostrstream будет записывать результат непосредственно в этот буфер. Это очень важное отличие от stringstream, в котором нет никаких подобных возможностей для помещения результата непосредственно в существующий буфер во избежание излишнего перераспределения памяти . Конечно, ostrstream может использовать и собственный динамически выделенный буфер, если у вас нет своего - для этого вам нано просто воспользоваться конструктором ostrstream по умолчанию . Из всех рассматриваемых в этом разделе альтернатив такая возможность эффективной работы есть только у strstream.

3. Безопасность в плане переполнения буфера. Как видно из примера 3-3, у ostrstream его внутренний буфер strstreambuf автоматически проверяет свою длину, чтобы обеспечить невозможность записи за пределами вьщеленной памяти. Если же мы используем конструктор ostrstream по умолчанию, то его внутренний буфер при необходимости будет автоматически увеличиваться.

4. Безопасность типов. Так же, как и stri ngstream, strstream полностью безопасен в этом отношении.

5. Возможность работы в шаблонах. Так же, как и stri ngstream, обеспечивает такую возможность. Вот небольшой пример, иллюстрирующий се.

tempiate<typename т>

void PrettyFormatC т value, char* buf, int buf1 en ) { ostrstream temn( buf, buflen ); temp setw(4) value << ends;

Подводя итоги, получаем следующую таблицу сравнения strstream с spri ntf.

У stri ngstream есть конструктор, который получает в качестве параметра stri ng&, но oil просто делает копию содержимого переданной строки вместо непосредственного использования этой строки в качестве рабочей области,

В табл. 3.1 исследования производительности strstream показаны всего лишь для двух компиляторов - Borland С++ 5.5.1 и Visual С++ 7. Дело в том, что в этих реализациях С++ по каким-то причинам при каждом вызове функции PrettyFormatC) из примера 3-3 выполняются дополнительные вьщеления памяти (хотя при передаче конструктору указателя на существующий буфер вьщелений памяти оказывается меньше, чем когда strstream создает собсттзениый буфер). Прочие среды, как и ожидалось, работают без дополиителыюго выделения памяти,



strstream

sprintf

Стандартность?

Да: (С++03], хотя и

объявлен

нежелательным

Да: (С90], [С++031, C99J

Простота использования и ясность?

Эффективность, без излишних распределений памяти?

Безопасность в плане переполнения буфера?

Безопасность типов?

Использование в шаблонах

Несколько смущает тот факт, что настолько хорошая вещь оказалась вдруг нежелательной, но такова жизнь...

Альтернатива №4: boost::lexicaLcast г) boost::1exical cast

Если вы еще незнакомы с Boost [Boost], мой совет - познакомьтесь. Это открытая библиотека для С-ь + , написанная в основном членами комитета по стандартизации С++, которая представляет собой не только пример хорошего кода, паписашюго профессионалами в стиле стандартной библиотеки С+ + . Возможности этой библиотеки, по сути, претендуют на включение в очередной стандарт С+-, так что с ними стоит ознакомиться заранее. Кроме того, вы можете использовать се сейчас и совершенно бесплатно.

Одна из интересных возможностей, предусмотренных в Boost, -- boost: :lexical cast, которая представляет собой оболочку вокруг stringstream. Boost включает также более мощные подходы, которые используют внутренние потоки и обеспечивают большое количество опций форматирования, в частности, boost: :format, но поскольку код, написанный Кэвлином Хенни (Kevlin Henncy), предельно краток и очень элегантен, я МОР) полиостью представить его здесь (исключив обходные nyiTi .оля старых компиляторов). И я делаю это, несмотря на то, что это - иеста1щарт11ая возможность.

tempiate<typename Target, typename Source> Target 1exical cast( Source arg ) {

std::stri ngstream interpreter;

Target result;

i f(!(i nterpreter arg) !(i nterpreter result) j

!(interpreter >> std::ws).eot()) throw bad lexical cast(); return result;

Заметим, что шаблон 1 exi cal cast не предназначен для конкуренции с гораздо более мощным средством форматирования строк, таким как spri ntf. 1 exi cal cast предназначен для конвертирования данных из одного типа в другой, так что он может представить конкуренцию скорее для функций С типа atoi () и подобных. OflttaKo данный шаблон настолько близок рассматриваемой теме, что пе упомянуть о нем просто невозможно.

Ниже представлен пример 3-1 при использовании 1 exi cal cast (требование вывода как минимум 4 си.мволов удалено).

Пример 3-4: строковое представление данных в С++ с использованием boost::1exical cast.



void PrettyFormatC int i, string& s ) { предельно просто: s = ]exical..cast<string>C i ) ;

/. Простота использования и ясность. Не стоит и доказывать, что данный код проще и понятнее всех ранее рассмотренных вариантов.

2. Эффективность (возможность непосредственного использования существующих буферов). Поскольку lexical cast использует stri ngstream, не удивительно, что при работе он требует выделения памяти, как минимум, в том же количестве, что и stri ngstream. На одной из опробованных мною платформ в примере 3-4 было выполнено на одно выделение памяти больше, чем требуется при использовании обычного stri ngstream (см. пример 3-2); на другой платформе дополнительного выделения памяти не было.

В остальных аспектах........ безопасности и возможности использования в шаблонах - 1exical cast соответствует stri ngstream.

Результаты сравнения lexical cast и spri ntf представлены в следующей таблице.

!exical cast

sprintf

Стандартность?

Нет (возможный кандидат Да; С90], [С--ьОЗ], [C99J в стандарт С-ы-Ох)

Простота использования и ясность?

Эффективность, без излишних распределений памяти?

Безопасность в плане переполнения

буфера

Безопасность типов?

Использование в шаблонах?

Резюме

Конечно, ряд вопросов не бьгл рассмотрен на.ми подробно. Например, все форматирование строк рассматривалось нами только в отношении обычных символов, а во-ггросы использования широких символов нами не затрагивались. Кроме того, вопросы эффективности затрагивались нами в плане непосредственного использования существующих буферов, но другая сторона этой эффективности - необходимость управления памятью программистом при использовании sprintf, snprintf и strstream, в то время как применение stri ngstream, strstream и 1 exi cal cast позволяет вам избежать этого. (Здесь нет опечатки или противоречия, strstream внесен в оба списка в связи с тем, что его можно использовать и так, и этак.)

Помимо 1 exi calcast, рассмотренного здесь в силу его краткости и элегантности, имеется масса других нестандартных альтернатив функции sprintf, в том числе в самой библиотеке Boost (например, такая замечательная и очень мощная вещь, как boost: : format, позволяющая добавить форматирование в стиле spri ntf к уже рассмотренным stri ngstream и strstream).

После обобщения результатов исследований мы получили сводную табл. 3,1, из которой понятно, что идеального варианта не существует, но, тем не Metiee, можно дать определенные рекомендации, которые сведены в табл. 3.2.

Если необходимо преобразовать значение в строку string (или во что-то иное) - используйте boost: : 1 exical cast.



1 ... 3 4 5 [ 6 ] 7 8 9 ... 84

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика