将使用auto-keyword声明的lambda通过非const引用作为参数传递给std :: function参数类型

Jee*_*eet 9 c++ lambda c++11

请考虑以下代码:

#include <iostream>
#include <functional>

// passing function object by value
void foo(std::function<int(int, int)> f) {
    std::cout << f(3, 7) << std::endl;
}

// passing const function object by reference
void bar(const std::function<int(int, int)> & f) {
    std::cout << f(3, 7) << std::endl;
}

// passing non-const function object by reference
void fizz(std::function<int(int, int)> & f) {
    std::cout << f(3, 7) << std::endl;
}

int main() {

    std::function<int(int, int)> g1 = [] (int x, int y) { return x * y; };
    auto g2 = [] (int x, int y) { return x * y; };

    foo(g1);   // OK
    foo(g2);   // OK
    bar(g1);   // OK
    bar(g2);   // OK
    fizz(g1);  // OK

    // compile error:
    // error: invalid initialization of reference of type
    // 'std::function<int(int, int)>&' from expression of type
    // 'main()::<lambda(int, int)>'
    // error: in passing argument 1 of 'void fizz(std::function<int(int, int)>&)'
    fizz(g2);

}
Run Code Online (Sandbox Code Playgroud)

有人会向我解释:

(a)为什么会fizz(g2)生成编译错误,而其他结构却没有?似乎我可以通过引用传递一个lambda,如果我在其声明中明确地键入它的类型,但是如果我使用auto关键字则不是,或者如果我将函数参数类型声明为const.

(二)什么 const的函数参数类型的意思是在这里吗?

(C) 在什么情况下我更愿意通过价值而不是参考(更新:现在一个单独的问题:C++ 11:通过引用或值传递(lambda或其他)函数对象?)?

感谢您的任何见解.

Nic*_*las 10

在你的fizz(g1)情况下,g1已经是一个std::function.因此,不需要隐式转换.所以fizz参数是非const引用g1.

fizz(g2),g2不是一个std::function.因此,编译器必须执行隐式转换.而隐式转换返回一个临时的.

临时对象不能绑定到非const引用; 它们只能绑定到const引用或值.因此编译错误.

函数参数类型中的const是什么意思?

您只能调用const该对象的成员,您不能将其隐式转换为非const,并且您不能const对其成员执行非操作.

你知道,就像任何其他用途const.

一般来说,当一个函数通过非const引用获取一个参数时,它会说一些关于它打算用该参数做什么的特别之处.也就是说,你正在处理一个对象,并且它会用它做非常量的东西(即:修改那个对象).这就是为什么temporaries不绑定到非const引用; 这可能是用户的错误,因为临时可能不会更新您传递的原始对象.

除非fizz实际上要修改对象,否则应该通过值或通过它传递它const&.

  • @ MarcJ.Schmidt:`g2`是一个唯一的类型,其名称不能由用户编写,就像所有lambdas一样.每个lambda表达式都会生成一个唯一类型.作为变量的`g2`的类型可以通过`decltype(g2)`来查询,但除此之外,你不能知道它是什么类型. (2认同)