Бьерн Страуструп. Язык программирования С++. Специальное издание (2011) (1004033), страница 166
Текст из файла (страница 166)
) о' массив по умолчанию о' придаем г размер и элементы Это позволяет избежать копирования большого объема данных. Если же мы захотим, чтобы массив га1аггау с ценными данными рос динамически, нужно обратиться к временному хранилишу: юЫО«ою(га(аггау<(и(>ь в, яэе ги) ( 0 (и<=в.з!ье() ) ге!игл! га1аггау<т!> 1тр (и) ! 2г п умолчательных элементов Сору(во[0], ьи[г.яге() ], ьгтр[0] ) ! /'копируюи(ий алгоритм из ь!Об! г.«еяте(п) ! сору(ытр [д], ытр [г.зйе() ], во[0] ) ! ) юЫО«ою2(га(аггау<гпг>ь г, ясе ! п) ( г3(и<=в.иге() ) ге!игл! га!аггау<ьш> Иир = г! з!(се з (О, г.з!ге (), 1) ! У подмоссив из кз(эе() элементов (см. 02245) У гез(ге() не сохраняет значения элементов скопируем элементы назад в начальную часть ч и.гезйе(п) г[з] = иир Если по какой-то причине ввод данных организован так, что узнать число вводимых данных можно лишь пересчитав их, то лучше сначала ввести данные в кон- Но это не основное предназначение массивов оа1аггау.
Тип га1аггау рассчитан на то, что после инициализации размер массива этого типа не меняется. Элементы массива ю1аггау формируют последовательность, так что г [ О] .. г [ и-1] располагаются в памяти друг за другом. Это означает, что для ва1аггау< Т> Т' является итератором произвольного доступа [в]9.2.1), и можно использовать стандартные алгоритмы, такие как сору(), например.
Однако лучше в духе га!аггау применять для копирования операцию присваивания и подмассивы: 78б Глава 22. Классы для математических вычислений тейнер типа «есгог (516.3.5), и только потом копировать элементы в массив «а!оп ау. 22.4.4. Внейние операции и функции Обычные бинарные операции и математические функции определены для массивов «а1аггау: гетпрМе<с!алв Т> «а1оггау<Т> орегагог* (сопл! «а(аггау<Т>ь, сопл! «а!аггау<Т>ь) гегпр!иге<с!аев Т> «а1апау<Т> орегагог* (сопл! «а!аггау<Т>ь, сопл! Ть ); гетпр1а!е<с1авв Т> «а!а««ау<7> орегагог* (соне! Ть, сопл! «а!апау<Т>ь) т гУанологично: Куи ч., —, ",&, ), «,», &&, )), ==,1=,<, >, <=,>=, атап2 и рот« !етр(иге<с!алл Т> «агаггау<Т> вол (сопл! «а!аггау<Т>ь); гУ аналогично: асов, агйп, агап, сок сох)ь ехр, 1ое, !ох!О, Мп, л!пЬ,л уг, гап и топд Бинарные операции определяются для двух операндов «а1апау, а также для «а!агтау и его скалярного типа.
Например: «оИ !(«агаггау<йоиЫе>ь «, «а!аггву<йоиЫе>ь «2, йоиЫе а) 1 «а1апау<йоиЫе> «3 = «*«2; «а!аггау<йоиЫе> «4 = «*ат «а!оп ау<йоиЫе> «5 = а' «2; У «ЗЯ = «(1] ч«2/!/ для всех 1 У «4Я = «Я«а' для всех 1 У «5Я = а'«2Я для всех 1 «а(аггау<йоиЫе> «6 = сов(«); У«бЯ = сов(«!г/) для всех) ) 22.4.5. Срезы Срез (лйсе) — это абстракция, которая позволяет эффективно работать с векторами как с матрицами произвольной размерноспги. Это ключевое понятие для векторов языка рог)гав и библиотеки ВТАБ (Вагйс 1.шеаг А18еЬга БцЬрго8гашз), являющейся базисом для многих численных расчетов. В своей основе срез — это каждый и-ый элемент некоторой части «а1аггау: Все эти операции применяются ко всем элементам операндов (операнда) способом, показанным в примере для * и сов() .
Естественно, операция применима лишь в том случае, когда она имеет смысл для типа аргумента шаблона. В противном случае компилятор выдаст ошибку в момент конкретизации шаблона (813.5). Там, где результат имеет тип «а!а««ау, длина получающегося массива та же, что и у операндов типа «а1ап ау. В случае разной длины операндов «а1аггау результат бинарных операций не определен.
Довольно любопытно, но для «а1агтау не предоставляется никаких операций ввода/вывода (822.4.3); «и» являются операциями сдвига. В то же время, можно легко определить версии операций « и » для ввода/вывода (822.915)). Заметьте, что рассматриваемые операции возвращают новый «а1аггау, а не модифицируют свои операнды. Это может дорого стоить, но может и не стоить, если для реализации «а!а««ау применяется агрессивная оптимизация (см., например, з22.4.7). Все эти операции и математические функции над массивами «а!а««ау можно применять и к в!!се апау (822,4,7), у!!се аггау (в22.4.8), таей аггау (822.4.9), 1иг!!гес! аггау (522.4.10) и к комбинациям этих типов. В то же время, реализации могут преобразовывать эти типы в «а1аггау перед выполнением операций.
2В2 22.4. Векторная арифметика с!аяя яЫ:: я!!се ( /У начальный индекс, длина и и<аг риЫ<с: яйсе() < яйсе(я(ге <я<оп, яге < я!ге, яге <яиЫе) яге <я<аг<() сопи; яге <яйе() сопя; яге < я<гЫе ( ) соля; ,У индекс первого элемента // число элементов /Уп-ый элемент налодитсн по У адресу: маг<() мп ея<пде() Здесь <наг (я<гЫе) — это расстояние (в элементах) между последовательными элементами среза.
Таким образом, срез определяется последовательностью целых чисел. Например, следуюц(ий код я!ге <яйсе (л<(ех(соля<яйсеь я, яге <!) ( гетгп я.яап() + <*я.ягЫе() < ) коЫ рпп< лед (сопя< яйсеь я) //вывод элементов среза я ( уог (яге «' = О< !<я. яге (); <++) сои< «яйсе !л«ех (я, <) « ) выведет 048, 159, 0123, 456 7. Другими словами, срез описывает отображение неотрицательных целых в индексы. Число элементов (я!ге ( ) ) не влияет на отображение, а просто позволяет нам найти конец последовательности.
Такое отображение позволяет имитировать двумерные массивы внутри одномерного массива (такого как еа1аггау) эффективно, универсально и относительно просто (удобно). Рассмотрим матрицу 3 на 4 так, как мы часто ее себе представляем (ВС.7): ной<<() ( рпп< лед (яйсе (0,3,4) ); сои<«", "; рпп< яед(яйсе(1,3,4) ); сои< « рг<п' яец (яйсе (О 4 1) ) сои<« рг[п< яее(яйсе(4 4 1) ) ) // строка О й строка ! й столбец 0 У столбец 1 788 Глава 22 Классы для математических вычислений По правилам языка гопгап она располагается в памяти следующим образом: 0 4 8 О 0 О О 0 1 2 3 В С++ массивы располагаются в памяти иначе (5С.7).
Однако нам нужно представить концепцию в рамках ясного и логического интерфейса, а затем уж учитывать ограничения, налагаемые конкретным представлением. Я выбрал расположение в стиле языка гопгап для того, чтобы упростить взаимодействие с программами численных расчетов, следующими этому соглашению. Однако я все же не зашел так далеко, чтобы начинать индексацию с единицы, а не с нуля; это оставляется в качестве упражнения (522.9[9)). Многие вычисления выполняются н будут выполняться с применением разных языков программирования и множества различных библиотек.
А потому часто важно иметь возможность манипулировать данными в разных форматах, соответствующих этим языкам и библиотекам. Строку с номером х можно представить срезом хйсе(х,3, 4) . То есть первым элементом строки х является х-ый элемент вектора, следующий элемент этой строки есть (хл4) -ый элемент вектора и т.д., и в каждой строке всего 3 элемента.
В соответствии с рисунками з!(са(0, 3, 4) описывает нулевую строку с 00, 01 и 02. Столбец у можно представить срезом х!(се(4"у, 4, 1). То есть первым элементом столбца с номером у является 4*у-ый элемент вектора, следующим элементом этого столбца — (4'у+1) -ый элемент вектора и т.д., и в каждом столбце всего 4 элемента. В соответствии с рисунками х!(се(0, 4, 1) описывает нулевой столбец с 00, 10, 20и 30. Кроме моделирования двумерных массивов срезы можно использовать для описания и других последовательностей. Они являются довольно универсальным средством представления простых последовательностей. Эта идея подробнее рассматривается в 522.4.8.
Еше можно рассматривать срезы как необычный вид итераторов, ведь они позволяют задать последовательности индексов для га!аэгау. На этой основе можно построить настоящий итератор: гетр(а!с<с!ат Т> с(алл Б!Гсе (гег ( га(аггау<Т>* ю адсе л! э(се ! сигг; У индекс текущего элемента Ть геГ(те г !) сопи (ге!игл (*г) (э имаг! () л(*л.эгг(4е О ); ) 22.4. Векторная арифметика 789 риЫк < Я<се «ег(га!аггау<Т>* гг, <1<сеял): г(гг), я(яя), сиге(0) () Я!се йег еп«() сопя< ( В!!се Йег< = *<Ыя; <.сип = я.я<те() ' ге<ига « ) УУ нндекс эл-то, следующего эа последним Я<се йегя орега<ог+э() (сшт+э< ге(игп *1ЬЫ; ) 51!се 1(ег орега1огээ (Ы<) (51<се аег ~ *<а<я< сиге+'-< гегигп << ) Тя орега<ог[) (Ыяе «) (ге<ига ге1'(1); ) У!индекса«ил в стиле С Тя орега<ог(] [я<ее « ) (ге<игл ге1'[!) < ) УУ индексация в стиле го((гап Тя орега<ог* () (ге<игп ге1 [сиге); ) УУ текущий элемент (г!еп<( ьоо! орега(ог==(сопя< а(!се «ега р, сопя( я<се вбегя я) < Тпеп<(Ьоо! орега<ог! =(сопя<Яке 1(егя р, соня(Я(се аегя а); 1пеп<(Ьоо! орега(ог<(сопя Я(се (<егй р, сопи Яке (<егя о) < (етр1а(е<с1аяя Т> Ьоо! орега<ог== (соп(а5!ке йег<Т>я р, сопя< Яке йег<Т>й о) ( ге<ига р.
сиге==о. сиге ай р.я. я(гЫе () ==«. я. я<г!ае () 6 6 р.я. кап () ==о. я. я<а(< ( ) < ) (етр!а(е<с!аяя Т> Ьоо! орега(ог! = (сопя< я(се 1<ег<Т> я р, сопя( я<се «ег<Т>я <() ( ге<ига ! (р==о); <етр1а(е<с!аяя Т> Ьоо! орега(ог< [сонм $1!се «ег<Т>я р, сопя< 51ке «ег<Т>я а) ( ге(игп р. снег<о. сигг я я р, я. я<с<ее ( ) ==« .я. <агЫе ( ) а 6 р. я. я<аг( ( ) ==[[.