std::function是否兼容值传递与const引用传递的签名?
std::function兼容不同参数签名的问题解答
这是标准C++的合法特性吗?
这是标准C++规定的合法特性,并非GCC 11的编译器扩展。
std::function的设计本身就支持兼容参数类型的可调用对象:只要被存储的可调用对象能够接受std::function签名中定义的实参(即实参可以隐式转换为可调用对象的参数类型),就可以被构造到std::function中。
在你的代码场景里:
- std::function的签名是
void(S const&),调用时传入的临时对象S{}会被绑定到S const&类型的参数上; - 对于参数为
S的lambda来说,S const&类型的实参可以通过隐式拷贝构造转换为S类型,满足lambda的参数要求,因此可以用来构造std::function。
调用端如何确定传引用还是拷贝?
调用端(函数f)不需要关心具体是传引用还是拷贝,它只需要严格按照std::function的签名void(S const&)传递参数——也就是传递一个绑定到临时对象S{}的S const&左值引用。
具体是引用还是拷贝,完全由被存储的可调用对象(lambda)的参数类型决定:
- 当lambda参数是
S const&时,直接引用传入的临时对象,不会发生拷贝; - 当lambda参数是
S时,会将S const&引用的对象拷贝一份,作为lambda的参数使用——这个拷贝操作是在std::function的调用操作符执行时完成的,属于std::function对可调用对象的适配过程。
代码示例
定义部分:
struct S { int a{3}; }; using callback = std::function<void(S const&)>; void f(callback&& cb) { cb(S{}); }
主函数部分:
int main() { f([](S const& s) { std::cout << s.a << std::endl; }); f([](S s) { s.a = 5; std::cout << s.a << std::endl; }); return 0; }
内容的提问来源于stack exchange,提问作者SupAl
相关产品推荐
相关产品推荐

