Чтение онлайн

на главную - закладки

Жанры

Эффективное использование STL
Шрифт:

Функция

stringLenghSum
является типичным представителем обобщающих функций, используемых при вызове
accumulate
. Функция получает текущее значение суммы и следующий элемент интервала, а возвращает новое значение накапливаемой суммы. Накапливаемая сумма (сумма длин строк, встречавшихся ранее) относится к типу
string::size_type
, а обрабатываемый элемент относится к типу
string
. Как это часто бывает, возвращаемое значение относится к тому же типу, что и первый параметр функции.

Функция

stringLenghSum
используется в сочетании с
accumulate
следующим образом:

set<string> ss; // Создать контейнер строк

… // и заполнить его данными

string::size_type lengthSum = // Присвоить lengthSum

 accumulate(ss.begin, ss.end, // результат вызова stringLengthSum

 0, stringLengthSum); // для каждого элемента ss

// с нулевым начальным значением

Изящно, не правда ли? Произведение вычисляется еще проще, поскольку вместо написания собственной функции суммирования можно обойтись стандартным функтором

multiplies
:

vector<float> vf; // Создать контейнер типа float

… // и заполнить его данными

float product = // Присвоить product результат

 accumulate(vf.begin, vf.end, // вызова multiplies<float>

 1.0, multples<float>); // для каждого элемента vf

// с начальным значением 1.0

Только не забудьте о том, что начальное значение вместо нуля должно быть равно единице (в вещественном формате, не в

int
!). Если начальное значение равно нулю, то результат всегда будет равен нулю — ноль, умноженный на любое число, остается нулем.

Последний пример не столь тривиален. В нем вычисляется среднее арифметическое по интервалу точек, представленных структурами следующего вида:

struct Point {

 Point(double initX, double initY): x(initX), y(initY) {}

 double x, y;

};

В этом примере обобщающей функцией будет функтор

PointAverage
, но перед рассмотрением класса этого функтора стоит рассмотреть его использование при вызове
accumulate
:

list<Point> lp;

Point avg = // Вычисление среднего

 accumulate(lp.begin, lp.end, // арифметического по точкам,

 Point(0,0), PointAverage); // входящим в список lр

Просто и бесхитростно, как и должно быть. На этот раз в качестве начального значения используется

объект
Point, соответствующий началу координат, а нам остается лишь помнить о необходимости исключения этой точки из вычислений.

Функтор

PointAverage
отслеживает количество обработанных точек, а также суммы их компонентов 
x
и
y
. При каждом вызове он обновляет данные и возвращает средние координаты по обработанным точкам. Поскольку для каждой точки в интервале функтор вызывается ровно один раз, он делит суммы по составляющим 
x
и 
y
на количество точек в интервале. Начальная точка, переданная при вызове
accumulate
, игнорируется.

class PointAverage:

 publiс binary_function<Point, Point, Point> {

public:

 PointAverage: xSum(0), ySum(0), numPoints(0) {}

 const Point operator (const Point& avgSoFar, const Point& p) {

++numPoints;

xSum += p.x;

ySum += p.y;

return Point(xSum/numPoints, ySum/numPoints);

 }

private:

 size_t numPoints;

 double xSum;

 double ySum;

};

Такое решение прекрасно работает, и лишь из-за периодических контактов с неординарно мыслящими личностями (многие из которых работают в Комитете по стандартизации) я могу представить себе реализации STL, в которых возможны проблемы. Тем не менее,

PointAverage
нарушает параграф 2 раздела 26.4.1 Стандарта, который, как вы помните, запрещает побочные эффекты по отношению к функции,передаваемой
accumulate
. Модификация переменных
numPoints
,
xSum
и
ySum
относится к побочным эффектам, поэтому с технической точки зрения приведенный выше фрагмент приводит к непредсказуемым последствиям. На практике трудно представить, что приведенный код может не работать, но чтобы моя совесть была чиста, я обязан специально оговорить это обстоятельство.

Впрочем, у меня появляется удобная возможность упомянуть о

for_each
— другом алгоритме, который может использоваться для обобщения интервалов. На
for_each
не распространяются ограничения, установленные для
accumulate
. Алгоритм
for_each
, как и
accumulate
, получает интервал и функцию (обычно в виде объекта функции), вызываемую для каждого элемента в интервале, однако функция, передаваемая
for_each
, получает только один аргумент (текущий элемент интервала), а после завершения работы
for_each
возвращает свою функцию (а точнее, ее копию — см. совет 38). Что еще важнее, переданная (и позднее возвращаемая) функция может обладать побочными эффектами.

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

Я Гордый часть 2

Машуков Тимур
2. Стальные яйца
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я Гордый часть 2

Князь Мещерский

Дроздов Анатолий Федорович
3. Зауряд-врач
Фантастика:
альтернативная история
8.35
рейтинг книги
Князь Мещерский

Тринадцатый VII

NikL
7. Видящий смерть
Фантастика:
фэнтези
попаданцы
аниме
5.25
рейтинг книги
Тринадцатый VII

Наследие Маозари 9

Панежин Евгений
9. Наследие Маозари
Фантастика:
попаданцы
постапокалипсис
рпг
сказочная фантастика
6.25
рейтинг книги
Наследие Маозари 9

Страж Кодекса. Книга IV

Романов Илья Николаевич
4. КО: Страж Кодекса
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Страж Кодекса. Книга IV

Эмиссар

Листратов Валерий
8. Ушедший Род
Фантастика:
боевая фантастика
аниме
попаданцы
7.50
рейтинг книги
Эмиссар

Антология странного рассказа

Коллектив авторов
Проза:
современная проза
5.00
рейтинг книги
Антология странного рассказа

Я – Легенда

Гарцевич Евгений Александрович
1. Я - Легенда!
Фантастика:
боевая фантастика
попаданцы
рпг
фантастика: прочее
5.00
рейтинг книги
Я – Легенда

Имперец. Том 5

Романов Михаил Яковлевич
4. Имперец
Фантастика:
попаданцы
альтернативная история
аниме
6.00
рейтинг книги
Имперец. Том 5

Телохранитель Генсека. Том 4

Алмазный Петр
4. Медведев
Фантастика:
попаданцы
альтернативная история
6.00
рейтинг книги
Телохранитель Генсека. Том 4

Идеальный мир для Лекаря 16

Сапфир Олег
16. Лекарь
Фантастика:
боевая фантастика
юмористическая фантастика
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 16

Вечный. Книга III

Рокотов Алексей
3. Вечный
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Вечный. Книга III

Моров. Том 4

Кощеев Владимир
3. Моров
Фантастика:
фэнтези
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Моров. Том 4

Наследник

Назимов Константин Геннадьевич
3. Травник
Фантастика:
фэнтези
6.80
рейтинг книги
Наследник