从常量和引用的角度来看,函数应该如何接受*lambda*参数



以下各项的行为有何不同?

我不清楚const对函数参数有什么影响,在这种情况下,通过值传递、通过引用传递或通过右值引用传递之间有什么区别。

请注意,我理解按值传递和按引用传递之间的区别。不过,在std::function的特定情况下,或者更具体地说是lambda,我不确定按值传递lambda与按引用传递lambda的区别。通过值传递lambda意味着什么?将要复制的数据是什么?

此外,const和不涉及lambdas之间是否有任何实际区别?

#include <functional>
void foo_with_func(      std::function<void()>   f) { ...; f(); ...; }
void foo_with_func(      std::function<void()>&  f) { ...; f(); ...; }
void foo_with_func(      std::function<void()>&& f) { ...; f(); ...; }
void foo_with_func(const std::function<void()>   f) { ...; f(); ...; }
void foo_with_func(const std::function<void()>&  f) { ...; f(); ...; }
void foo_with_func(const std::function<void()>&& f) { ...; f(); ...; }

所有使用相同:

foo_with_func([&]() { ... });

给定拟定用途foo_with_func([&]() { ... });

void foo_with_func(      std::function<void()>&  f) { ...; f(); ...; }

将不会编译,因为它将非常量左值引用绑定到临时值。其余部分在任何像样的优化编译器中都是等效的。如果您还想用std::function<void()> func;调用它,那么通过传递常量左值引用可能比通过传递值更有效。

然而,它们中没有一个是最有效的,因为所有这些都会产生类型擦除成本。为了避免这些成本,请编写一个模板并直接接受lambda。

template<class F>
void foo_with_func(F f){ f(); }

如果lambda按值捕获,并且复制成本可能很高,那么也可以使用F&&

经验法则:

常量参数

普通的旧数据类型,如double, int,char,应该通过值(副本)传递。它们适合处理器寄存器,而且任何其他机制都可能需要更多的处理或内存。

较大的数据结构应通过常量引用传递。将较大的结构复制到堆栈上会占用大量内存,并且需要额外的处理。传递引用意味着您正在引用一个现有项。传递常量引用意味着函数不会更改引用的项。

可变参数

将由函数修改的参数应通过引用传递。这允许您的程序"就地"修改项目。

注意:我还没有玩过移动语义,所以我不能推荐是否使用移动语义

最新更新