9

考虑以下代码:

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

}

有人可以向我解释一下:

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

(b)这里的函数参数类型是什么意思 const

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

感谢您的任何见解。

4

1 回答 1

10

在您的fizz(g1)情况下,g1已经是std::function. 因此,不需要隐式转换。所以fizz的参数是对 的非常量引用g1

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

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

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

只能调用const对象的成员,不能将其隐式转换为 non- const,也不能const对其成员执行 non- 操作。

你知道const,就像.

一般来说,当一个函数通过非常量引用获取一个参数时,它说明了它打算如何处理该参数的一些非常特殊的事情。也就是说,您将一个对象交给它,并且它将用它做非常量的事情(即:修改该对象)。这就是临时变量不绑定到非常量引用的原因。这可能是用户的错误,因为临时可能不会更新您传递的原始对象。

除非fizz实际上要修改对象,否则您应该按值或按const&.

于 2013-04-13T05:36:10.003 回答