C++ std::for_each和std::transform中函子的正确使用

C++ std::for_each和std::transform中函子的正确使用,c++,c++11,functor,C++,C++11,Functor,这可能是一个幼稚的问题,但不管怎么说,它是这样的: 假设我有一个这样的类: class func { public: int operator()(int it) const { return it + 21; } }; 很明显,上述类中定义了函子,如果我这样做: func obj; int capture = obj(9); cout << capture << endl; 我遵循以下语法,直接使用类名调用functor,并且根据定义,没有参

这可能是一个幼稚的问题,但不管怎么说,它是这样的:

假设我有一个这样的类:

class func {
    public:
        int operator()(int it) const { return it + 21; }
};
很明显,上述类中定义了函子,如果我这样做:

func obj;
int capture = obj(9);
cout << capture << endl;
我遵循以下语法,直接使用类名调用functor,并且根据定义,没有参数传递给functor:

std::transform(v.begin(), v.end(), vi.begin(), func());
这很好用。为什么会发生这种情况?尽管没有使用func的实例,也没有传递参数(显然是第一个容器的元素),但为什么这样做呢

此外,如果我使用func的一个实例,并像上面那样使用参数,则会导致编译错误

 func instance;
 std::transform(v.begin(), v.end(), vi.begin(), instance());
如何在std::transform/std::for_中正确使用函子?为什么在调用functor方法的方式上存在差异

另外,从中,我们有以下代码:

// this is a functor
struct add_x {
  add_x(int x) : x(x) {}
  int operator()(int y) const { return x + y; }

  private:
    int x;
};

std::vector<int> in; // assume this contains a bunch of values)
std::vector<int> out(in.size());
// Pass a functor to std::transform, which calls the functor on every element 
// in the input sequence, and stores the result to the output sequence
std::transform(in.begin(), in.end(), out.begin(), add_x(1));
答案是,add_x1在这里充当函子,而不是一个实例,在我给出的上述示例中,它是如何作为一个实例的

std::transform(v.begin(), v.end(), vi.begin(), lambda_function());
//                                             ^^^^^^^^^^^^^^^^^
这并不是调用lambda_函数::操作符,而是创建lambda_函数的临时实例。在std::transform内部,该对象将使用v的内容作为参数迭代调用其运算符

如果使用C++11的大括号初始化,情况会更明显:

std::transform(v.begin(), v.end(), vi.begin(), lambda_function{});

或者也许你认为这是:

lambda_function()(0);
//             ^^    creates instance
//               ^^^ calls operator()
关于你的第二个例子:

std::transform(in.begin(), in.end(), out.begin(), add_x(1));
//                                                ^^^^^^^^
std::transform(v.begin(), v.end(). vi.begin(), lambda_function());
这会再次创建add_x的临时实例,但它不会调用默认构造函数,而是调用add_xint x;构造器。这将初始化函数对象中的某些状态,以便在std::transform中调用运算符时,它会添加给定的数字。

在本例中

std::transform(v.begin(), v.end(), vi.begin(), lambda_function());
lambda_函数默认值创建lambda_函数的临时实例。 lambda_函数是一个类,而不是一个对象。 lambda_函数是一个对象

您没有传递实例,而是尝试调用没有参数的运算符。 实例是一个对象,而不是一个类

要传递实例,请编写

lambda_function instance;
std::transform(v.begin(), v.end(), vi.begin(), instance);
std::transformInIt first、InIt last、OutIt dest、Fn f本质上是这样做的:

while (first != last) {
    *dest = f(*first);
    first++;
}
所以当你打电话的时候

std::transform(v.begin(), v.end(). vi.begin(), lambda_function());
您正在创建lambda_函数类型的临时对象,并将该对象传递给transform。在转换内部,该对象会在输入范围的每个元素上被调用,就像在代码int capture=obj9;中一样

要使用已创建的对象而不是临时对象,只需传入:

lambda_function instance;
std::transform(v.begin(), v.end(), vi.begin(), instance);
注意,此代码没有after实例;这将是无参数调用运算符,而lambda_函数没有无参数调用的运算符。

请参见区别:

lambda_function obj;
int capture = obj(9);
cout << capture << endl;
vs

最新例子:

std::transform(in.begin(), in.end(), out.begin(), add_x(1));
vs


这是一个实例:lambda_函数。如果它是一个实例,在没有参数的情况下,它如何作为一个函子工作?它不应该引发编译错误吗?当代码与lambda函数和捕获无关时,为什么要调用lambda_函数和捕获?您链接的答案似乎对functor类及其实例都使用了术语functor,这对初学者来说可能有点混乱。非初学者通常可以从上下文中判断它是指一个类还是一个类的实例。Addixx1是一个函数对象,它是Addixx函子类的一个实例。如果它不调用函子,它是如何取每一个元素并加21的?函数是在算法内调用的。如果它不是一个实例,而是一个真正的函子,那么它是如何工作的?@Jarvis看看我在这个问题下的评论是否更清楚。实际上,不完全是这样的,add_x1如何向第一个容器的每个元素添加1,而add_xint y的定义如何向类成员x添加y?另外,add_x1是构造函数调用还是函子调用?
int capture = lambda_function()(9);
cout << capture << endl;
std::transform(v.begin(), v.end(). vi.begin(), lambda_function());
lambda_function obj;
std::transform(v.begin(), v.end(). vi.begin(), obj);
std::transform(in.begin(), in.end(), out.begin(), add_x(1));
add_x obj( 1 );
std::transform(in.begin(), in.end(), out.begin(), obj);