Анимация
JavaScript
|
Главная Библионтека
Таблица 3.2. Правила применения методов форматирования строк По умолчанию, когда эффективность не так важна Там, где эффективность важна, и профилирование подтверждает необходимость оптимизации Простое конвертирование в строковое представление Простое форматирование .!Иоо работа с широкими строка.ми или в шаблонах Сложное форматирование при отсутствии необходимости в работе с широкими строками или в шаблонах boost: : 1 exi cal „cast std:;stri ngstream или std::strstream snprintf std::strstream или snprintf std::strstream или snprintf snpri ntf В заключение отмстим несколько интересных возможностей, предусмотренных в strstream. Не последняя из них -- возможность выбора .между использованием встроенного или предоставляемого программистом буфера. Его существенный технический недостаток состоит в определенной "хрупкости", связанной с необходимостью использования завершения строки при помощи ends. Важный (назовем его "социальным") недостаток заключается в том, что следует учитьшать (пусть и небольшую) вероятность того, что в один прекрасный день и комитет по стандарту С+ + , и производитель вашего компилятора решат избавиться от strstream. Честно говоря, очень странно видеть такую хорошую вещь нежелательной. Как видим, даже в стандарте некоторые животные равнее других,,. Проводилось усреднение по трем запускам каждой программы, в которых выполнялось по 1 млн, вызовов кода соо~ветствующих примеров. Результаты мог>т зависеть от используемых версии компиляторов и опций компиляции Задача 4. Функции-члены стандартной библиотеки Сложность: 5 Повторное использование - это хорошо, но всегда ли допустимо использование возможностей стандартной библиотеки с ней самой? Вот небольшой пример, который может вас удивить. В нем рассматривается возможность стандартной библиотеки, которая может быть переносимо использована с любым вашим кодом, но только не с самой стандартной библиотекой. Вопрос для новичка 1. Что такое std: :mem fun? Когда можно использовать std: : mem„f un? Приведите пример. Вопрос для профессионала 2. Полагая, что в комментарии в приведенном коде все правильно, ответьте на вопрос: является ли приведенный код корректным и переносимым кодом С-+? Обоснуйте свой ответ. std::mem fun</*...*/>( &std::vector<int>::clear ) Решение Игры с mem fun 1. Что такое std: : mem...fun? Когда можно использовать std: :mem f un? Приведите пример. Стандартньп-i адаптер mem„fun позволяет нам использовать функции-члены в алгорит-,мах ставдартиой библиотеки и другом коде, который обычно работает с функииями, не являющимися членами класса (свободными функциями). Пусть, например, мь! имеем class Employee { publi с: int DoStandardRai se() { /...-/ } int Gi veStandardRai se( Employee& e ) { return e.DoStandardRaiseC); std::vector<Employee> emps; Мы >же привыкли писать, например, следующим образом. std::for„each( emps.beginC), emps.end(), &GiveStandardRaise ); Ho что, если функции Gi veStandardRai se() не существует или по каким-то иным причинам нам надо вызвать функцию-член не;10срсдствснно? Тогда мы можем написать следующий код. std:;vector<Emplоуее> emps; std::for„each(emps.begi nC), emps.end(), std : : rr.em f un„ref (&Empl oyee : : DoStandardRai se)) ; Суффикс „ref в конце mem fun ref - дань историческим тр;а.дициям. Когда мы пишем код наподобие приведенного, мы просто должны помнить, что надо использовать mem fun ref, если имеем дело с обычным контейнером с объектами и for eath работает со ссылками на эти объекты, и использовать nem„.fun. cl.ih контейнер содержит указатели на объекты. std::vector<Employee*> emp ptrs; std::for each(emp ptrs.begin(), emp ptrs.end(), std::mem „fun(&Employee::DoStandardRai se)); Вы, вероятно, обратили внимание, что для ясности я воспользовался функцией без параметров. Вы можете воспользоваться вспомогательными классами bind... для функций с аргументом - принцип при этом остается тот же. К сожалению, вы не можете использовать этот подход для функций с двумя и более параметрами. Вот, по сути, главное, что надо знать о mem „fun. И это подводит нас к трудной части задачи. Используйте mem fun, но не со стандартной библиотекой 2. Полагая, что в комментарии в приведенном коде все правильно, ответьте на вопрос: является ли приведенный код корректным и переносимым кодом С++? Обоснуйте свой ответ. std::mem fun</*...*/>( &std::vector<int>::cl ear ) Я специально сформулировал вопрос таким образом (с комментарием вместо аргумента шаблона), поскольку некоторые распространенные компиляторы в такой ситуации не в состоянии корректно вывести аргументы шаблона. Для них, в зависимости от ваи]сй реализации стандартной библиотеки, может потребоваться написать что-то наподобие std: :mem fun<void, std: :vector<int, std: :anocator<int> > > ( &std::vector<int>::clear); Co временем это ограничение должно быть ликвидировано, и компиляторы будут позволять опускать параметры шаблонов. Вы можете удивиться моим примечанием "в зависимости от вашей реализации стандартной библиотеки". В конце концов, сигнатура std: : vector<i ni>: : clear гласит, что эта функция не получает параметров и ничего не возвращает, ведь так? Разве стандарт не говорит нам об этом? По сути, в этом и заключается главный вопрос задачи. Спецификация стандартной библиотеки сознатель[то предоставляет разработчикам определенную свободу действий по реализации функций-членов. В частности: • еи1 натура функции-члена с параметрами по умолчанию может бьпъ заменена "двумя или более сигнатурами функций-членов с эквивалентным поведением"; • сигнатура функции-члена может иметь дополнительные параметры по умолчанию. Второй пункт и есть главная неприятность. Все эти "может быть или не быть", игры в прятки с дополнительными параметрами и привели к появлению данной задачи. В большинстве случаев в этом нет никаких проблем, и все эти параметры по умолчанию просто остаются незамеченными. Например, при вызове функции-члена эти скрытые параметры, которых вы не передаете, попадают в функцию в виде значений по умолчанию, и вы даже не подозреваете об их существовании. Но, к сожалению, эти параметры начинают играть важную роль, когда ста1ювится важна точная сигнатура функции - например, когда вы пытаетесь использовать mem„fun, За.метим, что это происходит, даже если ваш компилятор корректно выводит аргументы шаблонов. Это связано с двумя потенциальными проблема.ми. • Если рассматриваемая функция-член полчает параметр, о котором вы не подозревали, вам понадобится написать что-то наподобие std:; bi nd2nd для того, чтобы избавиться от него (более подробное описание использования стандартных замыканий параметров функции можно найти в [Josuttis99j)- Конечно, после этого ваш код ие будет работать в реализации, где используется дополнительный 0 1 2 3 4 5 6 7 [ 8 ] 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |