开发者

A question about for_each in vector of c++

I have a question about the for_each in vector, the code is following:

#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;
}

should the third argument of for_each() be a function name? if we pass the name 开发者_如何学Pythonof the struct, how does this works?


This is a functor.

std::for_each is a function template that basically expands to this:

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

So myobject can either be a function pointer, or it can be an object with an overload for operator().


The third argument of for_each can be anything that behaves like a function, i.e. that can be invoked like x(). Since your struct overloads operator(), it has precisely this behaviour.

Classes which overload the ()-operator are called "functors" or "function objects". Their power lies in the fact that you can store additional data (e.g. accumulators or inital values) in the class members while still behaving like an ordinary function.


Not necessarily. for_each expects an object that can be called like a function (a functor). In other words, an object that overloads operator()(T) where T is the type of the values held in the container on which for_each is applied.


You are not passing a type or (quote) "name of a struct", but rather an object. The syntax

struct Foo {
} foo;

actually declares the type Foo and on object foo of type Foo.

Passing function objects instead of function pointers is prefered. See also this about why.


The code is pretty well explained where, I think, you found it:

The source of the code.

The example on the site looks like this:

// 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;
}


It's not a function name, it's a function object (functor).

You can either do this manually yourself by defining a class with suitable operator() implementation, or wrap a function as a functor using Boost.Function or similar.

Note that there is a subtle issue here. If you define your operator() as you have here, the code works, but cannot be used to update the vector elements. If you wish to update in place, you need to define instead as (for example):

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

This is more typically how functors are defined - arguments are passed by reference rather than by value.


Since you are overloading operator () (int) for myclass, the function name is resolved from the struct itself. See for_each for more info.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜