Вход/Регистрация
Программирование. Принципы и практика использования C++ Исправленное издание
вернуться

Страуструп Бьерн

Шрифт:

x.apply(f); // x[i] = f(x[i]) для каждого i

В результате

a==b
и
x==y
.

В языке Fortran второй вариант функции
apply
называется функцией пересылки (“broadcast” function). В этом языке чаще пишут вызов
f(x)
, а не
apply(f,x)
. Для того чтобы эта возможность стала доступной для каждой функции
f
(а не только для отдельных функций, как в языке Fortran), мы должны присвоить операции пересылки конкретное имя, поэтому (повторно) использовали имя apply.

Кроме того, для того чтобы обеспечить соответствие с вариантом функции-члена

apply
, имеющим вид
a.apply(f,x)
, мы пишем

b = apply(f,a,x); // b[i]=f(a[i],x) для каждого i

Рассмотрим пример.

double scale(double d, double s) { return d*s; }

b = apply(scale,a,7); // b[i] = a[i]*7 для каждого i

Обратите внимание на то, что “автономная” функция

apply
принимает в качестве аргумента функцию, вычисляющую результат по ее аргументам, а затем использует этот результат для инициализации итогового объекта класса
Matrix
. Как правило, это не приводит к изменению объекта класса
Matrix
, к которому эта функция применяется. В то же время функция-член
apply
отличается тем, что принимает в качестве аргумента функцию, модифицирующую ее аргументы; иначе говоря, она модифицирует элементы объекта класса
Matrix
, к которому применяется. Рассмотрим пример.

void scale_in_place(double& d, double s) { d *= s; }

b.apply(scale_in_place,7); // b[i] *= 7 для каждого i

В классе

Matrix
предусмотрено также много полезных функций из традиционных математических библиотек.

Matrix<int> a3 = scale_and_add(a,8,a2); // объединенное умножение

// и сложение

int r = dot_product(a3,a); // скалярное произведение

Операцию
scale_and_add
часто называют объединенным умножением и сложением (fused multiply-add), или просто fma; ее определение выглядит так:
result(i)=arg1(i)*arg2+arg3(i)
для каждого
i
в объекте класса
Matrix
. Скалярное произведение также известно под именем
inner_product
и описано в разделе 21.5.3; ее определение выглядит так:
result+=arg1(i)*arg2(i)
для каждого
i
в объекте класса
Matrix
, где накопление объекта
result
начинается с нуля.

Одномерные массивы очень широко распространены; их можно представить как в виде встроенного массива, так и с помощью классов

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

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

Класс

Matrix
имеет два конструктора для копирования данных из встроенных массивов в объект класса
Matrix
. Рассмотрим пример.

void some_function(double* p, int n)

{

double val[] = { 1.2, 2.3, 3.4, 4.5 };

Matrix<double> data(p,n);

Matrix<double> constants(val);

// ...

}

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

Matrix
.

Обратите внимание на то, что компилятор может самостоятельно определить количество элементов в инициализированном массиве, поэтому это число при определении объекта

constants
указывать не обязательно — оно равно —
4
. С другой стороны, если элементы заданы всего лишь указателем, то компилятор не знает их количества, поэтому при определении объекта
data
мы должны задать как указатель
p
, так и количество элементов
n
.

24.5.3. Двумерный объект класса Matrix

Общая идея библиотеки

Matrix
заключается в том, что матрицы разной размерности на самом деле в большинстве случаев очень похожи, за исключением ситуаций, в которых необходимо явно указывать размерность. Таким образом, большинство из того, что мы можем сказать об одномерных объектах класса
Matrix
, относится и к двумерным матрицам.

Matrix<int,2> a(3,4);

  • Читать дальше
  • 1
  • ...
  • 383
  • 384
  • 385
  • 386
  • 387
  • 388
  • 389
  • 390
  • 391
  • 392
  • 393
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: