mic*_*ael 5 c++ pass-by-reference functor stdbind auto
假设我想传递一个通过std::bind
引用 funktion 创建的函数对象:
void myCallback(int i, int j)
{
std::cout << "toCall , i=" << i << " j=" << j;
}
void worker(std::function<void(int)> & callback)
{
callback(111);
}
int main(int argc, char** argv)
{
auto foo = std::bind(myCallback, std::placeholders::_1, 222);
worker(foo);
}
Run Code Online (Sandbox Code Playgroud)
这不能编译
严重性代码说明项目文件行抑制状态错误 C2664 'void worker(std::function &)': 无法将参数 1 从 'std::_Binder &,int>' 转换为 'std::function &' asn1test_1 D:.. ...\asn1test_1.....cpp 302
然而,按值传递是有效的:
void worker(std::function<void(int)> callback)
{
callback(111);
}
Run Code Online (Sandbox Code Playgroud)
当我避免使用“ auto
”并改为使用
std::function<void(int)> foo = std::bind(myCallback, std::placeholders::_1, 222);
Run Code Online (Sandbox Code Playgroud)
它既可以通过引用传递,也可以通过值传递。
Q1:为什么会有这种行为?
std::bind
Q2:将创建的对象传递给函数的“正确”方式或数据类型是什么?
std::bind
不返回 a std::function
,至少不需要这样做。当你这样做时
auto foo = std::bind(myCallback, std::placeholders::_1, 222);
worker(foo);
Run Code Online (Sandbox Code Playgroud)
foo
不是 astd::function
并且worker
需要对 a 的非常量引用std::function
,因此编译器会出错。如果你切换worker
到
void worker(const std::function<void(int)> & callback)
Run Code Online (Sandbox Code Playgroud)
那么您将拥有一个 const 引用,并且可以将其绑定到转换foo
为 astd::function
将产生的临时对象。
我还想指出,由于我们有 lambda,尤其是泛型,所以std::bind
实际上并不需要。将更改保留给工人,您可以改为foo
auto foo = [](auto var){ return myCallback(var, 222); };
Run Code Online (Sandbox Code Playgroud)
std::bind()
不返回 a ,而是返回可转换为 a 的std::function
实现定义类型。std::function
当worker()
将其callback
参数作为非常量引用时,会阻止编译器执行任何隐式转换,因为非常量引用无法绑定到临时对象。该引用需要std::function
事先显式创建一个实际对象,例如:
std::function<void(int)> foo = std::bind(myCallback, std::placeholders::_1, 222);
worker(foo);
Run Code Online (Sandbox Code Playgroud)
更改worker()
为按值或常量引用获取其参数,允许编译器为您执行隐式转换,因此您可以按原样callback
传递结果,编译器将为您创建一个临时值。std::bind()
std::function
它应该是:
void worker(std::function<void(int)> const& callback) {
callback(111);
}
Run Code Online (Sandbox Code Playgroud)
因为这样就可以进行从foo
临时对象的隐式转换。std::function