函数指针中使用右值引用作为参数的优势是什么?
关于std::function右值引用传参的优势
我在代码中看到了这样的函数写法:
void subMyCallback3(MyCallback&& callback) { callback(1); }
于是写了测试代码验证,但没发现它和普通传参的明显区别:
测试代码:
#include <iostream> #include <functional> #include "stdio.h" using namespace std; using MyCallback = std::function<void(int x)>; void subMyCallback1(MyCallback callback) { printf("%p\n", &callback); callback(1); } void subMyCallback3(MyCallback&& callback) { printf("%p\n", &callback); callback(1); } int main() { auto func = [](int x) { std::cout << x << std::endl; }; printf("%p\n", &func); subMyCallback1(func); subMyCallback3(std::move(func)); return 0; }
输出结果:
0x7fff8ade477f 0x7fff8ade4780 1 0x7fff8ade4780 1
请问使用右值引用作为std::function参数的优势是什么?
核心优势解析
你的测试例子用的是空捕获lambda,std::function的拷贝成本极低,所以看不出差异。但在实际业务场景中,右值引用传参有两个关键价值:
避免不必要的拷贝开销
std::function内部会存储可调用对象(比如带捕获的lambda、绑定了对象成员的函数器)。如果捕获的是大对象(比如std::vector<int>、自定义的重型类实例),传值调用会触发整个std::function的拷贝,包括内部捕获对象的拷贝,带来明显的性能损耗。而右值引用可以直接转移std::function的内部资源所有权,完全避免拷贝操作。举个实际场景的例子:
void pass_by_value(std::function<void()> f) { f(); } void pass_by_rvalue_ref(std::function<void()>&& f) { f(); } int main() { std::vector<int> big_data(1000000, 1); auto func = [big_data]() { /* 使用big_data做计算 */ }; // 传值:拷贝整个big_data到std::function内部,开销极大 pass_by_value(func); // 右值引用:转移func的内部资源,无拷贝开销 pass_by_rvalue_ref(std::move(func)); }支持仅可移动的可调用对象
有些可调用对象是只能移动不能拷贝的,比如捕获了std::unique_ptr的lambda。这种情况下,传值调用会直接编译报错,而右值引用可以接收这类对象并正常使用。例子:
void pass_by_rvalue_ref(std::function<void()>&& f) { f(); } int main() { auto ptr = std::make_unique<int>(42); // 捕获unique_ptr,该lambda仅可移动 auto func = [ptr = std::move(ptr)]() { std::cout << *ptr << std::endl; }; // pass_by_value(func); // 编译错误:unique_ptr不可拷贝 pass_by_rvalue_ref(std::move(func)); // 正常运行,输出42 }
另外补充:你测试中看到的地址相同是栈地址分配的巧合——右值引用本身是函数形参的引用,它的栈地址刚好和传值的形参地址重合,不代表两者没有拷贝差异。
内容的提问来源于stack exchange,提问作者Qwe Qwe
相关产品推荐
相关产品推荐

