Анимация
JavaScript


Главная  Библионтека 

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 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239

Возведение всех элементов коллекции в квадрат выполняется аналогично:

transform (coll.beginO. coll.endO. Первый источник

coll.beginO. Второй источник

coll .beginO . Приемник

mult1pl1es<int>0): Операция

На этот раз другая форма алгоритма transform() объединяет элементы двух коллекций, 11рименяя к ним заданную операцию, и записывает результат в третью коллекцию. В данном примере во всех трех случаях используется одна и та же коллекция, поэтому каждый элемент умтюжается сам на себя, а результат записывается в исходную позицию .

Специальные фупкционалыше адаптеры позволяют объединять стандартные объекты функций с другими значениями или определять особые ситуации. Пример:

stl/fol.cpp #include <1ostream> #include <5et> #1nclude <deque> #include <algor1thm> #1nclude "print.hpp" using namespace std:

Int ma1nO {

set<int.greater<1nt> > colli; deque<1nt> col 12:

Вставка элементов со значениями от 1 до 9 for (int 1=1: 1<=9; ++1) { colU.insertd):

PRINT ELEMENTS(colU."initialized; О;

Преобразование всех элементов col 12 умножением на 10 transform (colli.beginO.colli.end(), Источник

backjnserter(coll2). Приемник

b1nd2nd(mult1pl1es<lnt>(),10)); Операция

PRINT ELEMENTS(con2."transforfTied; ");

Замена значения, равного 70, на 42

replacejf (со112.beginO,coll2.end(). Интервал

bind2nd(equal to<int>().70). Критерий замены

42); Новое значение

В предыдущих версиях STL объект функции, uыпo.иявшvlй умножение, назывался times. Переимеповаппс произошло из-за конфликта имен с функциями стандартов операционных систем (Х/Ореп, POSIX), а также потому, что имя multiplies более попятно.



PRINTJLEMENTS(coll 2. "replaced: "):

Удаление всех элементов со значениями, меньшими 50 coll2.erase(refflove if(coll2.beg1n(),coll2.end(). Интервал

b1nd2nd{less<int>().50)). Критерий удаления coll2.endC)):

PRINT ELEMENTSCcol12,"removed: ");

Следующая команда умножает каждый элемент colli на 10 и вставляет его в coiI2:

transform (colli.begln{),colli.endO. Источник

bdck 1nserter(coll2), Приемник

b1nd2nd(mult1plies<1nt>(),lO)); Операция

Функциональный адаптер bind2nd обеспечивает вызов multiplies<int> для каждого элемента исходной коллекции (первый аргумент) и множителя 10 (второй аргумент).

При вызове bind2nd() происходит следующее: в четвертом аргументе алгоритм transformO рассчитывает получить операцию, которая вызывается с одним аргументом (элементом, с которым она выполняется). В пашем примере аргумент умножается на 10. Следовательно, мы должны объединить операцию с двумя аргументами и постоянную величину, которая всегда будет использоваться вместо второго аргумента; в результате будет получена нужная операция с одним аргументом. Именно это и делает адаптер bind2nd(). Он сохраняет операцию и второй аргумент в своих внутренних данных. Когда aлJopитм вызывает адаптер bind2nd для конкретного элемента, вызывается операция с переданным элементом (первый аргумент) и внутренним значением (второй аргумент), а возвращается полученный результат.

В аналогичном фрагменте выражение bind2nd(equai to<int>(),70) определяет критерий отбора элементов, заменяемых значением 42:

replace if (coll2.begin().coll2.end().

bi nd2nd(equal to<int>().70). 42);

Адаптер bind2nd вызывает бинарный предикат equaLto со вторым аргументом, равным 70. Тем самым определяется унарный предикат для элементов обрабатываемой коллекции.

Последняя команда действует аналогично. Выражение bind2nd(Iess<int>(),50) определяет элементы, которые должны быть удалены из коллекции. Команда удаляет все элементы со значением меньше 50. Результат выполнения программы выглядит так:

initialized: 9 8 7 6 5 4 3 2 1

transformed: 90 80 70 60 50 40 30 20 10

replaced: 9D 80 42 60 5D 40 3D 20 10

removed: 9D 80 60 50



Подобный подход к программированию приводит к фупкциопальной композиции. Интересная подробность: все объекты функций обычно объявляются подставляемыми (inline). Таким образом, несмотря иа абстрактную функциональную запись, мы получаем хорошую производительность.

Сушествуют и другие разновидности объектов функций. Например, некоторые объекты функций позволяют вызвать определенную функцию класса для каждого элемента коллекции:

for edch Ccoll.beg1n(), coll.endO. Интервал

nen fun ref(&Person save)): Операция

Объект функции mem fun ref вызывает заданную функцию класса для того элемента, для которого этот объект вызывается. В приведенном примере для каждого элемента коллекции coil вызывается фупкция save() класса Person. Разумеется, эта конструкция работает только в том случае, если элемент относится к тину Person или производному от него.

На с. 305 перечислены и более подробно описаны все стандартные объекты функций, функциональные адаптеры и аспекты функциональной композиции. Кроме того, в этом разделе рассказано, как написать собственный объект функции.

Элементы контейнеров

Э.т1ементы контейнеров должны удовлетворять ряду требований, нотому что контейнеры работают с ними но определенным правилам. Настоящий раздел посвящен требованиям, предъявляемым к элементам. Кроме того, мы разберемся, к каким последствиям приводит создание контейнером внутренних копий элементов.

Требования к элементам контейнеров

Контейнеры, итераторы и алгоритмы STL оформлены в виде шаблонов. Это означает, что они могут работать с любыми тинами, как заранее определенными, так и пользовательскими. Впрочем, специфика выполняемых операций накладывает ряд требований на элементы контейнеров STL. Таких требований три.

О Требуется возмоэюиость копирования элемента копирующим конструктором. Созданная копия должна быть эквивалентна оригиналу. Это означает, что любая проверка на равенство должна считать копию и оригинал равными, а поведение копии не должно отличаться от поведения оригинала.

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



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 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239