Шаг 242.
Библиотека STL.
Объекты функций STL. Возвращаемое значение алгоритма for_each

    На этом шаге мы рассмотрим получение ссылки с помощью алгоритма for_each.

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

    Следующая программа хорошо поясняет, как использовать возвращаемое значение алгоритма for_each(). В ней вычисляется среднее арифметическое числовой последовательности.

//---------------------------------------------------------------------------

#include <vcl.h>
#include <iostream>
#include <iterator>
#include <vector>
#include <algorithm>

#include <conio.h> //необходимо для getch()

#pragma hdrstop

//---------------------------------------------------------------------------

#pragma argsused
using namespace std;


std::string ToRus(const std::string &in)
{
  char *buff = new char [in.length()+1];
  CharToOem(in.c_str(),buff);
  std::string out(buff);
  delete [] buff;
  return out;
}

template <class T>
inline void PRINT_ELEMENTS (const T& coll, const char* optcstr="")
{
  typename T::const_iterator pos;
  std::cout << ToRus(optcstr);
  for (pos=coll.begin(); pos!=coll.end(); ++pos) {
    std::cout <<*pos <<' ';
  }
  std::cout << std::endl;
}


// Объект функции для вычисления среднего арифметического
class MeanValue {
  private:
    long num;    // Счетчик элементов
    long sum;    // Сумма всех значений элементов
  public:
    // Конструктор
    MeanValue () : num(0), sum(0) {
    }

    // "Вызов функции"
    // - обработка очередного элемента последовательности
    void operator() (int elem) {
        num++;          // Увеличение счетчика
        sum += elem;    // Прибавление значения
    }

    // Возвращение среднего арифметического
    double value () {
        return static_cast<double>(sum) / static_cast<double>(num);
    }
};


int main(int argc, char* argv[])
{
  vector<int> coll;

  // Вставка элементов от 1 до 8
  for (int i=1; i<=8; ++i) {
      coll.push_back(i);
  }
  PRINT_ELEMENTS(coll,"Исходный вектор:\n");

  // Вычисление и вывод среднего арифметического
  MeanValue mv = for_each (coll.begin(), coll.end(),  // Интервал
                           MeanValue());              // Операция
  cout << ToRus("Среднее арифметическое: ") << mv.value() << endl;

  getch();
  return 0;
}

//---------------------------------------------------------------------------
Текст этого примера можно взять здесь.

    Вызов MeanValue() создает объект функции, который подсчитывает количество элементов и вычисляет сумму их значений. Передача этого объекта при вызове for_each() обеспечивает его вызов для каждого элемента контейнера coll:

  MeanValue mv = for_each (coll.begin(), coll.end(), 
                                            MeanValue());

    Объект функции, возвращенный алгоритмом for_each(), присваивается mv, поэтому после вызова можно запросить информацию о его состоянии в виде mv.value(). В итоге программа выводит следующий результат:


Рис.1. Результат работы приложения

    Класс MeanValue можно дополнительно усовершенствовать, определив автоматическое преобразование к типу double. В этом случае среднее арифметическое, вычисленное for_each(), можно будет напрямую использовать в программе.

    На следующем шаге мы рассмотрим предикаты и объекты функций.




Предыдущий шаг Содержание Следующий шаг