Вопрос про for_each в векторе c ++ - PullRequest
4 голосов
/ 01 июля 2011

У меня вопрос о for_each в векторе, код следующий:

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;


struct myclass {
  void operator() (int i) {cout << " " << i;}
} myobject;

int main () {
  vector<int> myvector(3,4);

  cout << "\nmyvector contains:";
  for_each (myvector.begin(), myvector.end(), myobject);

  cout << endl;

  return 0;
}

должен ли третий аргумент for_each () быть именем функции? если мы передадим имя структуры, как это работает?

Ответы [ 7 ]

8 голосов
/ 01 июля 2011

Это функтор .

std::for_each - это шаблон функции, который в основном расширяется до этого:

for (iter = myvector.begin(); iter != myvector.end(); ++iter)
{
    myobject(*iter);
}

Итак myobject может быть указателем на функцию или объектом с перегрузкой для operator().

2 голосов
/ 01 июля 2011

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

2 голосов
/ 01 июля 2011

Третий аргумент for_each может быть любым, что ведет себя как функция , то есть может вызываться как x(). Поскольку ваша структура перегружает operator(), она имеет именно такое поведение.

Классы, которые перегружают () -оператор, называются «функторами» или «функциональными объектами». Их сила заключается в том, что вы можете хранить дополнительные данные (например, аккумуляторы или начальные значения) в членах класса, продолжая вести себя как обычная функция.

1 голос
/ 01 июля 2011

Вы передаете не тип или (цитата) "имя структуры", а скорее объект.Синтаксис

struct Foo {
} foo;

фактически объявляет тип Foo и объект foo типа Foo.

Передача функциональных объектов вместо указателей функций является предпочтительной.Смотри также это о причинах.

0 голосов
/ 01 июля 2011

Код довольно хорошо объяснен, где, я думаю, вы его нашли:

Источник кода.

Пример на сайте выглядит следующим образом:

// for_each example
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

void myfunction (int i) {
  cout << " " << i;
}

struct myclass {
  void operator() (int i) {cout << " " << i;}
} myobject;

int main () {
  vector<int> myvector;
  myvector.push_back(10);
  myvector.push_back(20);
  myvector.push_back(30);

  cout << "myvector contains:";
  for_each (myvector.begin(), myvector.end(), myfunction);

  // or:
  cout << "\nmyvector contains:";
  for_each (myvector.begin(), myvector.end(), myobject);

  cout << endl;

  return 0;
}
0 голосов
/ 01 июля 2011

Это не имя функции, это объект функции (функтор).

Вы можете сделать это вручную, определив класс с подходящей реализацией operator(), или обернуть функцию как функтор, используя Boost.Function или аналогичный.

Обратите внимание, что здесь есть небольшая проблема.Если вы определите свой operator() как здесь, код работает, но не может быть использован для обновления векторных элементов.Если вы хотите обновить на месте, вам нужно определить вместо этого (например):

 void operator() (int& i) { i *= 2; } 

Это более типичный способ определения функторов - аргументы передаются по ссылке, а не по значению.

0 голосов
/ 01 июля 2011

Поскольку вы перегружаете operator () (int) для myclass, имя функции разрешается из самой структуры.См. for_each для получения дополнительной информации.

...