关于c ++向量中for_each的问题

时间:2011-07-01 11:59:57

标签: c++ stl vector struct foreach

我对向量中的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 个答案:

答案 0 :(得分:8)

这是functor

std::for_each是一个功能模板,基本上扩展为:

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

因此myobject可以是函数指针,也可以是operator()重载的对象。

答案 1 :(得分:2)

for_each的第三个参数可以是像函数那样的任何内容,即可以像x()一样调用它。由于你的struct重载operator(),它恰恰就是这种行为。

重载()-operator的类称为“functor”或“function objects”。它们的强大之处在于,您可以在类成员中存储其他数据(例如累加器或初始值),同时仍然表现得像普通函数。

答案 2 :(得分:2)

不一定。 for_each期望一个可以像函数一样被调用的对象(仿函数)。换句话说,一个重载operator()(T)的对象,其中T是应用for_each的容器中保存的值的类型。

答案 3 :(得分:1)

您没有传递类型或(引用)“结构名称”,而是传递对象。语法

struct Foo {
} foo;

实际上声明了Foo类型和foo类型的对象Foo

首选传递函数对象而不是函数指针。也可以看看 this关于原因。

答案 4 :(得分:0)

由于您为operator () (int)重载myclass,因此函数名称将从结构本身解析。有关详细信息,请参阅for_each

答案 5 :(得分:0)

它不是函数名,它是一个函数对象(仿函数)。

您可以通过定义具有合适operator()实现的类来自行手动执行此操作,也可以使用Boost.Function或类似功能将函数包装为仿函数。

请注意,这里有一个微妙的问题。如果您在此处定义operator(),则代码可以正常工作,但不能用于更新矢量元素。如果您希望更新到位,则需要将其定义为(例如):

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

更常见的是如何定义仿函数 - 参数通过引用而不是值传递。

答案 6 :(得分:0)

代码很好地解释了,我认为你找到了它:

The source of the code.

网站上的示例如下所示:

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