Обратите внимание на то, что компилятор может самостоятельно определить количество элементов в инициализированном массиве, поэтому это число при определении объекта
constants
указывать не обязательно — оно равно —
4
. С другой стороны, если элементы заданы всего лишь указателем, то компилятор не знает их количества, поэтому при определении объекта
data
мы должны задать как указатель
p
, так и количество элементов
n
.
24.5.3. Двумерный объект класса Matrix
Общая идея библиотеки
Matrix
заключается в том, что матрицы разной размерности
на самом деле в большинстве случаев очень похожи, за исключением ситуаций, в которых необходимо явно указывать размерность. Таким образом, большинство из того, что мы можем сказать об одномерных объектах класса
Matrix
, относится и к двумерным матрицам.
Matrix<int,2> a(3,4);
int s = a.size; // количество элементов
int d1 = a.dim1; // количество элементов в строке
int d2 = a.dim2; // количество элементов в столбце
int* p = a.data; // извлекаем данные с помощью указателя в стиле
// языка С
Мы можем запросить общее количество элементов и количество элементов в каждой размерности. Кроме того, можем получить указатель на элементы, размещенные в памяти в виде матрицы.
Мы можем использовать индексы.
a(i,j); // (i,j)-й элемент (в стиле языка Fortran) с проверкой
// диапазона
a[i]; // i-я строка (в стиле языка C) с проверкой диапазона
a[i][j]; // (i,j)-й элемент (в стиле языка C)
В двумерном объекте класса
Matrix
индексирование с помощью конструкции
[i]
создает одномерный объект класса
Matrix
, представляющий собой
i
– ю строку. Это значит, что мы можем извлекать строки и передавать их операторам и функциям, получающим в качестве аргументов одномерные объекты класса
Matrix
и даже встроенные массивы
(a[i].data)
. Обратите внимание на то, что индексирование вида
a(i,j)
может оказаться быстрее, чем индексирование вида
a[i][j]
, хотя это сильно зависит от компилятора и оптимизатора.
Мы можем получить срезки.
a.slice(i); // строки от a[i] до последней
a.slice(i,n); // строки от a[i] до a[i+n–1]
Срезка двумерного объекта класса
Matrix
сама является двумерным объектом этого класса (возможно, с меньшим количеством строк). Распределенные операции над двумерными матрицами такие же, как и над одномерными. Этим операциям неважно, как именно хранятся элементы; они просто применяются ко всем элементам в порядке их следования в памяти.
Matrix<int,2> a2 = a; // копирующая инициализация
a = a2; // копирующее присваивание
a *= 7; // пересчет (и +=, –=, /= и т.д.)
a.apply(f); // a(i,j)=f(a(i,j)) для каждого элемента a(i,j)
a.apply(f,7); // a(i,j)=f(a(i,j),7) для каждого элемента a(i,j)
b=apply(f,a); //
создаем новую матрицу с b(i,j)==f(a(i,j))
b=apply(f,a,7); // создаем новую матрицу с b(i,j)==f(a(i,j),7)
Оказывается, что перестановка строк также полезна, поэтому мы предусмотрим и ее.
не существует. Если она вам потребуется, то вы сможете написать ее самостоятельно (см. упр. 11). Из-за построчной схемы хранения матриц в памяти строки и столбцы не совсем равноправны. Эта асимметрия проявляется также в том, что оператор
[i]
возвращает только строку (а для столбцов аналогичный оператор не предусмотрен). Итак, в тройке
(i,j)
первый индекс
i
выбирает строку. Эта асимметрия имеет глубокие математические корни.
Количество действий, которые можно было бы выполнить над двумерными матрицами, кажется бесконечным.
Однако он не работает (по крайней мере, пока не появится новая версия языка C++ (C++0x)), поэтому пока приходится прибегать к трюкам с инициализацией массива (в данном случае
init_pos
) и использовать его для инициализации объектов класса
Matrix
. Мы можем использовать объекты
start_row
и
clear_row
следующим образом:
board[white_start_row] = start_row; // расставить белые фигуры
for (int i = 1; i<7; ++i) board[i] = clear_row; // очистить середину
// доски
board[black_start_row] = start_row; // расставить черные фигуры
Обратите внимание на то, что когда мы извлекли строку, используя выражение
[i]
, мы получили значение
lvalue
(см. раздел 4.3); иначе говоря, мы можем присвоить результат элементу
board[i]
.
24.5.4. Ввод-вывод объектов класса Matrix
Библиотека
Matrix
предоставляет очень простые средства для ввода и вывода одно- и двухмерных объектов класса